@titan-design/code-graph 0.10.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store.ts","../src/schema.ts","../src/rows.ts","../src/store-reads.ts","../src/prune.ts","../src/indexer.ts","../src/extractors/ts-morph-extractor.ts","../src/extractors/file-nodes.ts","../src/extractors/ids.ts","../src/extractors/reference-weight.ts","../src/scope-path.ts","../src/declared-names.ts","../src/extractors/call-sites.ts","../src/extractors/callable-params.ts","../src/extractors/symbol-signature.ts","../src/extractors/symbol-nodes.ts","../src/extractors/dynamic-imports.ts","../src/extractors/module-resolution.ts","../src/extractors/reexport-resolve.ts","../src/extractors/ts-calls.ts","../src/extractors/ts-scope.ts","../src/extractors/python-extractor.ts","../src/extractors/python-calls.ts","../src/extractors/dispatch.ts","../src/git-renames.ts","../src/identity/lineage.ts","../src/identity/alias-chain.ts","../src/identity/store-identity.ts","../src/identity/index-aliases.ts","../src/generated.ts","../src/roles.ts","../src/file-walk.ts","../src/barrel-resolve.ts","../src/incremental.ts","../src/analysis/comment-lines.ts","../src/analysis/narrating-comments.ts","../src/analysis/exception-handling.ts","../src/cognitive-complexity.ts","../src/lcom.ts","../src/analysis/pass-through.ts","../src/symbol-metrics.ts","../src/source-metrics.ts","../src/analysis/dead-code-python.ts","../src/analysis/dead-code.ts","../src/analysis/growth-risk.ts","../src/reconstruct.ts","../src/reuse-delta.ts","../src/metrics.ts","../src/analysis/call-metrics.ts","../src/analysis/test-linker.ts","../src/history-recency.ts","../src/history-metrics.ts","../src/index-metrics.ts","../src/merge.ts","../src/symbol-aliases.ts","../src/index.ts","../src/extractors/deep-ast.ts","../src/aliases.ts","../src/analysis/coverage.ts","../src/analysis/pagerank.ts","../src/analysis/relevance.ts","../src/analysis/symbol-coupling.ts","../src/analysis/partition-quality.ts","../src/analysis/snapshot.ts","../src/read.ts","../src/catalogue/entries.ts","../src/catalogue/describe.ts","../src/check/context.ts","../src/check/patterns.ts","../src/check/rule-helpers.ts","../src/check/import-rules.ts","../src/check/violation-location.ts","../src/check/outlier-rule.ts","../src/check/metric-rules.ts","../src/check/rules.ts","../src/check/check.ts","../src/check/findings.ts","../src/check/finding-store.ts","../src/check/validate.ts","../src/check/run.ts","../src/diff/diff.ts","../src/diff/check-diff.ts","../src/diff/footprint.ts","../src/embeddings/corpus.ts","../src/embeddings/cache.ts","../src/embeddings/embeddings.ts","../src/conventions/communities.ts","../src/conventions/areas.ts","../src/conventions/summaries.ts","../src/conventions/query.ts"],"sourcesContent":["import { openDatabase, quoteIdent, runMigrations, type Db } from \"@titan-design/store-sqlite\";\nimport { MIGRATIONS, SCHEMA_VERSION, SNAPSHOT_SCOPED_TABLES } from \"./schema.js\";\nimport {\n prepareTargetedStatements,\n readEdgesTouching,\n readMetricAggregates,\n readMetricNames,\n readMetricsForNode,\n readTopByMetric,\n type MetricAggregate,\n type TargetedStatements,\n type TopMetricRow,\n} from \"./store-reads.js\";\nimport {\n rowToAlias,\n rowToEdge,\n rowToFingerprint,\n rowToMetric,\n rowToNode,\n rowToSnapshot,\n type AliasDbRow,\n type EdgeDbRow,\n type FingerprintDbRow,\n type MetricDbRow,\n type NodeDbRow,\n type SnapshotDbRow,\n} from \"./rows.js\";\nimport type {\n FileFingerprint,\n GraphEdge,\n GraphMetric,\n GraphNode,\n IdAlias,\n SnapshotRow,\n} from \"./types.js\";\n\nexport interface SnapshotInsert {\n ref: string;\n commitHash?: string;\n indexVersion: string;\n attrs?: Record<string, unknown>;\n}\n\nconst NODE_COLS = \"id, kind, name, parent_id, language, role, attrs\";\n\n/** Per-symbol `references` and `calls` edges sit below the file-level graph the default reads return. */\nfunction isStructuralLayer(edge: GraphEdge): boolean {\n return edge.kind !== \"references\" && edge.kind !== \"calls\";\n}\n\n/**\n * The code graph's query surface over store-sqlite's snapshot-scoped kit tables\n * plus this package's domain tables. Replaces codewatch's `GraphDatabase`: the\n * connection, pragmas, and migration runner are the kit's; what is left here is\n * the code-specific statements the indexer and its readers need.\n */\nexport class CodeGraphStore {\n private readonly statements;\n private readonly targeted: TargetedStatements;\n\n constructor(readonly db: Db) {\n this.statements = prepareStatements(db);\n this.targeted = prepareTargetedStatements(db);\n }\n\n createSnapshot(input: SnapshotInsert): number {\n const result = this.statements.insertSnapshot.run({\n ref: input.ref,\n commitHash: input.commitHash ?? null,\n indexVersion: input.indexVersion,\n attrs: JSON.stringify(input.attrs ?? {}),\n });\n return Number(result.lastInsertRowid);\n }\n\n insertNodes(snapshotId: number, nodes: readonly GraphNode[]): void {\n const stmt = this.statements.insertNode;\n this.db.transaction(() => {\n for (const n of nodes) {\n stmt.run({\n snapshotId,\n id: n.id,\n kind: n.kind,\n name: n.name,\n parentId: n.parentId ?? null,\n language: n.language ?? null,\n role: n.role ?? null,\n attrs: JSON.stringify(n.attrs ?? {}),\n });\n }\n })();\n }\n\n insertEdges(snapshotId: number, edges: readonly GraphEdge[]): void {\n const stmt = this.statements.insertEdge;\n this.db.transaction(() => {\n for (const e of edges) {\n stmt.run({\n snapshotId,\n srcId: e.srcId,\n dstId: e.dstId,\n kind: e.kind,\n attrs: JSON.stringify(e.attrs ?? {}),\n });\n }\n })();\n }\n\n insertMetrics(snapshotId: number, metrics: readonly GraphMetric[]): void {\n const stmt = this.statements.insertMetric;\n this.db.transaction(() => {\n for (const m of metrics) {\n stmt.run({ snapshotId, nodeId: m.nodeId, name: m.name, value: m.value, unit: m.unit ?? null });\n }\n })();\n }\n\n /**\n * Replace every metric of one `name` for a snapshot in a single transaction —\n * for an overlay such as coverage, which is re-ingested wholesale and must not\n * accumulate stale rows across runs.\n */\n replaceMetricsByName(snapshotId: number, name: string, metrics: readonly GraphMetric[]): void {\n const del = this.statements.deleteMetricsByName;\n const insert = this.statements.insertMetric;\n this.db.transaction(() => {\n del.run(snapshotId, name);\n for (const m of metrics) {\n insert.run({ snapshotId, nodeId: m.nodeId, name: m.name, value: m.value, unit: m.unit ?? null });\n }\n })();\n }\n\n insertAliases(snapshotId: number, aliases: readonly IdAlias[]): void {\n const stmt = this.statements.insertAlias;\n this.db.transaction(() => {\n for (const a of aliases) {\n stmt.run({ snapshotId, oldId: a.oldId, newId: a.newId, reason: a.reason });\n }\n })();\n }\n\n insertFingerprints(snapshotId: number, fingerprints: readonly FileFingerprint[]): void {\n const stmt = this.statements.insertFingerprint;\n this.db.transaction(() => {\n for (const f of fingerprints) {\n stmt.run({\n snapshotId,\n fileId: f.fileId,\n contentHash: f.contentHash,\n structuralHash: f.structuralHash ?? null,\n });\n }\n })();\n }\n\n getSnapshot(id: number): SnapshotRow | null {\n const row = this.statements.getSnapshot.get(id) as SnapshotDbRow | undefined;\n return row ? rowToSnapshot(row) : null;\n }\n\n listSnapshots(opts: { ref?: string; limit?: number } = {}): SnapshotRow[] {\n const limit = opts.limit ?? 50;\n const rows = (\n opts.ref\n ? this.statements.listSnapshotsByRef.all(opts.ref, limit)\n : this.statements.listSnapshots.all(limit)\n ) as SnapshotDbRow[];\n return rows.map(rowToSnapshot);\n }\n\n getLatestSnapshotByRef(ref: string): SnapshotRow | null {\n return this.listSnapshots({ ref, limit: 1 })[0] ?? null;\n }\n\n getNode(snapshotId: number, id: string): GraphNode | null {\n const row = this.statements.getNode.get(snapshotId, id) as NodeDbRow | undefined;\n return row ? rowToNode(row) : null;\n }\n\n /**\n * File-level structural graph by default: the per-symbol layer is excluded so\n * consumers that reason about module structure see the graph they expect. Pass\n * `includeSymbols` for the symbol layer (the reuse basis needs it).\n */\n listNodes(snapshotId: number, opts?: { includeSymbols?: boolean }): GraphNode[] {\n const nodes = (this.statements.listNodes.all(snapshotId) as NodeDbRow[]).map(rowToNode);\n return opts?.includeSymbols ? nodes : nodes.filter((n) => n.kind !== \"symbol\");\n }\n\n /** See {@link listNodes}: `references` and `calls` edges are the symbol layer, excluded by default. */\n listEdges(snapshotId: number, opts?: { includeReferences?: boolean }): GraphEdge[] {\n const edges = (this.statements.listEdges.all(snapshotId) as EdgeDbRow[]).map(rowToEdge);\n return opts?.includeReferences ? edges : edges.filter(isStructuralLayer);\n }\n\n listMetrics(snapshotId: number): GraphMetric[] {\n return (this.statements.listMetrics.all(snapshotId) as MetricDbRow[]).map(rowToMetric);\n }\n\n /** Every metric on one node, from the primary key instead of a whole-snapshot read. */\n listMetricsForNode(snapshotId: number, nodeId: string): GraphMetric[] {\n return readMetricsForNode(this.targeted, snapshotId, nodeId);\n }\n\n /** Distinct metric names stored for a snapshot, ascending. */\n listMetricNames(snapshotId: number): string[] {\n return readMetricNames(this.targeted, snapshotId);\n }\n\n /** The highest-valued nodes for one metric, descending; `limit` defaults to 20. */\n topByMetric(opts: { snapshotId: number; metric: string; limit?: number; kind?: string }): TopMetricRow[] {\n return readTopByMetric(this.targeted, opts);\n }\n\n /** Edges into or out of one node; symbol-layer edges are excluded unless asked, as in {@link listEdges}. */\n listEdgesTouching(snapshotId: number, nodeId: string, opts?: { includeReferences?: boolean }): GraphEdge[] {\n const edges = readEdgesTouching(this.targeted, snapshotId, nodeId);\n return opts?.includeReferences ? edges : edges.filter(isStructuralLayer);\n }\n\n /** Count, sum, min, and max per metric name and node kind; pass `name` for one metric. */\n aggregateMetrics(snapshotId: number, opts?: { name?: string }): MetricAggregate[] {\n return readMetricAggregates(this.targeted, snapshotId, opts?.name);\n }\n\n listAliases(snapshotId: number): IdAlias[] {\n return (this.statements.listAliases.all(snapshotId) as AliasDbRow[]).map(rowToAlias);\n }\n\n listFingerprints(snapshotId: number): FileFingerprint[] {\n return (this.statements.listFingerprints.all(snapshotId) as FingerprintDbRow[]).map(rowToFingerprint);\n }\n\n /** Drop whole snapshots. The domain tables carry no foreign key, so each is cleared by hand. */\n deleteSnapshots(ids: readonly number[]): void {\n if (ids.length === 0) return;\n this.db.transaction(() => {\n for (const id of ids) {\n for (const stmt of this.statements.deleteBySnapshot) stmt.run(id);\n }\n })();\n }\n\n vacuum(): void {\n this.db.exec(\"VACUUM\");\n }\n\n countRowsByTable(tables: readonly string[]): Record<string, number> {\n const out: Record<string, number> = {};\n for (const table of tables) {\n const row = this.db.prepare(`SELECT COUNT(*) AS n FROM ${quoteIdent(table)}`).get() as { n: number };\n out[table] = row.n;\n }\n return out;\n }\n\n close(): void {\n this.db.close();\n }\n}\n\nfunction prepareStatements(db: Db) {\n return {\n insertSnapshot: db.prepare(\n `INSERT INTO snapshot (ref, commit_hash, index_version, attrs)\n VALUES (@ref, @commitHash, @indexVersion, @attrs)`,\n ),\n insertNode: db.prepare(\n `INSERT OR REPLACE INTO node (snapshot_id, id, kind, name, parent_id, language, role, attrs)\n VALUES (@snapshotId, @id, @kind, @name, @parentId, @language, @role, @attrs)`,\n ),\n insertEdge: db.prepare(\n `INSERT OR REPLACE INTO edge (snapshot_id, src_id, dst_id, kind, attrs)\n VALUES (@snapshotId, @srcId, @dstId, @kind, @attrs)`,\n ),\n insertMetric: db.prepare(\n `INSERT OR REPLACE INTO metric (snapshot_id, node_id, name, value, unit)\n VALUES (@snapshotId, @nodeId, @name, @value, @unit)`,\n ),\n insertAlias: db.prepare(\n `INSERT OR REPLACE INTO id_alias (snapshot_id, old_id, new_id, reason)\n VALUES (@snapshotId, @oldId, @newId, @reason)`,\n ),\n insertFingerprint: db.prepare(\n `INSERT OR REPLACE INTO file_fingerprint (snapshot_id, file_id, content_hash, structural_hash)\n VALUES (@snapshotId, @fileId, @contentHash, @structuralHash)`,\n ),\n getSnapshot: db.prepare(\"SELECT * FROM snapshot WHERE id = ?\"),\n listSnapshots: db.prepare(\"SELECT * FROM snapshot ORDER BY taken_at DESC, id DESC LIMIT ?\"),\n listSnapshotsByRef: db.prepare(\n \"SELECT * FROM snapshot WHERE ref = ? ORDER BY taken_at DESC, id DESC LIMIT ?\",\n ),\n getNode: db.prepare(`SELECT ${NODE_COLS} FROM node WHERE snapshot_id = ? AND id = ?`),\n listNodes: db.prepare(`SELECT ${NODE_COLS} FROM node WHERE snapshot_id = ?`),\n listEdges: db.prepare(\"SELECT src_id, dst_id, kind, attrs FROM edge WHERE snapshot_id = ?\"),\n listMetrics: db.prepare(\"SELECT node_id, name, value, unit FROM metric WHERE snapshot_id = ?\"),\n listAliases: db.prepare(\"SELECT old_id, new_id, reason FROM id_alias WHERE snapshot_id = ?\"),\n listFingerprints: db.prepare(\n \"SELECT file_id, content_hash, structural_hash FROM file_fingerprint WHERE snapshot_id = ?\",\n ),\n deleteMetricsByName: db.prepare(\"DELETE FROM metric WHERE snapshot_id = ? AND name = ?\"),\n deleteBySnapshot: [...SNAPSHOT_SCOPED_TABLES, \"snapshot\"].map((table) =>\n db.prepare(`DELETE FROM ${quoteIdent(table)} WHERE ${table === \"snapshot\" ? \"id\" : \"snapshot_id\"} = ?`),\n ),\n };\n}\n\n/** Open (creating if absent) a code graph database and bring it to the current schema. */\nexport function openCodeGraph(dbPath: string): CodeGraphStore {\n const db = openDatabase(dbPath, { schemaVersion: SCHEMA_VERSION });\n runMigrations(db, MIGRATIONS);\n return new CodeGraphStore(db);\n}\n","import { kitMigration, type Migration } from \"@titan-design/store-sqlite\";\n\n/**\n * Kit table names. The code graph is snapshot-scoped end to end: a whole repo is\n * re-indexed together, so `snapshotTableDdl` + `entitySnapTableDdl` are the right\n * time model and the interval `edgeTableDdl` is not — one unchanged import would\n * otherwise write a row per file per snapshot. The edge table below is therefore\n * the snapshot-scoped counterpart, owned here.\n */\nexport const KIT = { snapshot: \"snapshot\", entitySnap: \"node\", cacheBlob: \"blob_cache\" } as const;\n\n/**\n * Two columns the kit's `entity_snap` shape does not carry but every consumer of\n * a code graph reads directly, plus the snapshot provenance the reuse basis\n * selects on. Kept as real columns rather than folded into `attrs` so the\n * vocabularies stay queryable and stay codewatch-compatible.\n */\nconst KIT_EXTENSIONS = `\n ALTER TABLE node ADD COLUMN language TEXT;\n ALTER TABLE node ADD COLUMN role TEXT;\n ALTER TABLE snapshot ADD COLUMN commit_hash TEXT;\n ALTER TABLE snapshot ADD COLUMN index_version TEXT NOT NULL DEFAULT '';\n`;\n\n/**\n * Domain tables. `edge` is the snapshot-scoped edge shape (the kit's own edge\n * table is bi-temporal); `metric` holds index-time measurements keyed by node;\n * `id_alias` carries a node id across a rename so two snapshots line up; and\n * `file_fingerprint` is the reuse basis the incremental indexer diffs against.\n */\nexport const DOMAIN_DDL = `\n CREATE TABLE IF NOT EXISTS edge (\n snapshot_id INTEGER NOT NULL,\n src_id TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n kind TEXT NOT NULL,\n attrs TEXT,\n PRIMARY KEY (snapshot_id, src_id, dst_id, kind)\n );\n CREATE INDEX IF NOT EXISTS idx_edge_dst ON edge(snapshot_id, dst_id);\n CREATE INDEX IF NOT EXISTS idx_edge_kind ON edge(snapshot_id, kind);\n\n CREATE TABLE IF NOT EXISTS metric (\n snapshot_id INTEGER NOT NULL,\n node_id TEXT NOT NULL,\n name TEXT NOT NULL,\n value REAL,\n unit TEXT,\n PRIMARY KEY (snapshot_id, node_id, name)\n );\n CREATE INDEX IF NOT EXISTS idx_metric_name ON metric(snapshot_id, name);\n\n CREATE TABLE IF NOT EXISTS id_alias (\n snapshot_id INTEGER NOT NULL,\n old_id TEXT NOT NULL,\n new_id TEXT NOT NULL,\n reason TEXT NOT NULL,\n PRIMARY KEY (snapshot_id, old_id, new_id)\n );\n\n CREATE TABLE IF NOT EXISTS file_fingerprint (\n snapshot_id INTEGER NOT NULL,\n file_id TEXT NOT NULL,\n content_hash TEXT NOT NULL,\n structural_hash TEXT,\n PRIMARY KEY (snapshot_id, file_id)\n );\n`;\n\n/**\n * Stored audit findings and model verdicts. `key` is a `findingKey`, not `Finding.id`,\n * because an external tool's id embeds its line number and can repeat within one audit.\n * The whole `Finding` and a verdict's citations live in `attrs`.\n */\nexport const FINDING_DDL = `\n CREATE TABLE IF NOT EXISTS finding (\n snapshot_id INTEGER NOT NULL,\n key TEXT NOT NULL,\n finding_id TEXT NOT NULL,\n tool TEXT NOT NULL,\n signal TEXT NOT NULL,\n path TEXT NOT NULL,\n line_start INTEGER,\n line_end INTEGER,\n severity TEXT NOT NULL,\n excerpt_hash TEXT,\n attrs TEXT NOT NULL,\n PRIMARY KEY (snapshot_id, key)\n );\n CREATE INDEX IF NOT EXISTS idx_finding_path ON finding(snapshot_id, path);\n\n CREATE TABLE IF NOT EXISTS verdict (\n snapshot_id INTEGER NOT NULL,\n key TEXT NOT NULL,\n verdict TEXT NOT NULL CHECK (verdict IN ('confirmed', 'justified', 'unclear')),\n rationale TEXT NOT NULL,\n excerpt_hash TEXT NOT NULL,\n model TEXT,\n run_id TEXT,\n cost_usd REAL,\n provenance TEXT,\n control_run TEXT,\n carried_from INTEGER,\n attrs TEXT NOT NULL,\n PRIMARY KEY (snapshot_id, key)\n );\n`;\n\n/** Every table keyed by `snapshot_id`. No DDL above declares a foreign key, so dropping a snapshot walks this list. */\nexport const SNAPSHOT_SCOPED_TABLES = [\n \"node\",\n \"edge\",\n \"metric\",\n \"id_alias\",\n \"file_fingerprint\",\n \"finding\",\n \"verdict\",\n] as const;\n\nexport const MIGRATIONS: Migration[] = [\n kitMigration(1, { snapshot: KIT.snapshot, entitySnap: KIT.entitySnap, cacheBlob: KIT.cacheBlob }),\n { version: 2, name: \"code graph columns\", up: (db) => db.exec(KIT_EXTENSIONS) },\n { version: 3, name: \"code graph tables\", up: (db) => db.exec(DOMAIN_DDL) },\n { version: 4, name: \"findings and verdicts\", up: (db) => db.exec(FINDING_DDL) },\n];\n\n/** The top of this package's schema. A code graph database is never shared, so this is the top of one. */\nexport const SCHEMA_VERSION = Math.max(...MIGRATIONS.map((m) => m.version));\n","import type {\n FileFingerprint,\n GraphEdge,\n GraphMetric,\n GraphNode,\n IdAlias,\n IdAliasReason,\n SnapshotRow,\n} from \"./types.js\";\n\n// Raw row shapes as stored in SQLite, paired with mappers to the domain types.\n// Kept separate from the connection/statement manager in database.ts.\n\nexport interface SnapshotDbRow {\n id: number;\n ref: string;\n commit_hash: string | null;\n taken_at: string;\n index_version: string;\n attrs: string;\n}\n\nexport interface NodeDbRow {\n id: string;\n kind: string;\n name: string;\n parent_id: string | null;\n language: string | null;\n role: string | null;\n attrs: string;\n}\n\nexport interface EdgeDbRow {\n src_id: string;\n dst_id: string;\n kind: string;\n attrs: string;\n}\n\nexport interface MetricDbRow {\n node_id: string;\n name: string;\n value: number | null;\n unit: string | null;\n}\n\nexport interface AliasDbRow {\n old_id: string;\n new_id: string;\n reason: string;\n}\n\nexport interface FingerprintDbRow {\n file_id: string;\n content_hash: string;\n structural_hash: string | null;\n}\n\nexport function rowToSnapshot(row: SnapshotDbRow): SnapshotRow {\n return {\n id: row.id,\n ref: row.ref,\n commitHash: row.commit_hash,\n takenAt: row.taken_at,\n indexVersion: row.index_version,\n attrs: JSON.parse(row.attrs) as Record<string, unknown>,\n };\n}\n\nexport function rowToNode(row: NodeDbRow): GraphNode {\n return {\n id: row.id,\n kind: row.kind as GraphNode[\"kind\"],\n name: row.name,\n parentId: row.parent_id ?? undefined,\n language: row.language ?? undefined,\n role: (row.role ?? undefined) as GraphNode[\"role\"],\n attrs: JSON.parse(row.attrs) as Record<string, unknown>,\n };\n}\n\nexport function rowToEdge(row: EdgeDbRow): GraphEdge {\n return {\n srcId: row.src_id,\n dstId: row.dst_id,\n kind: row.kind as GraphEdge[\"kind\"],\n attrs: JSON.parse(row.attrs) as Record<string, unknown>,\n };\n}\n\nexport function rowToMetric(row: MetricDbRow): GraphMetric {\n return {\n nodeId: row.node_id,\n name: row.name,\n value: row.value,\n unit: row.unit ?? undefined,\n };\n}\n\nexport function rowToAlias(row: AliasDbRow): IdAlias {\n return {\n oldId: row.old_id,\n newId: row.new_id,\n reason: row.reason as IdAliasReason,\n };\n}\n\nexport function rowToFingerprint(row: FingerprintDbRow): FileFingerprint {\n return {\n fileId: row.file_id,\n contentHash: row.content_hash,\n structuralHash: row.structural_hash ?? undefined,\n };\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport { rowToEdge, rowToMetric, type EdgeDbRow, type MetricDbRow } from \"./rows.js\";\nimport type { GraphEdge, GraphMetric, NodeKind } from \"./types.js\";\n\n/** One metric's values over the nodes of one kind in one snapshot; `count` excludes null values. */\nexport interface MetricAggregate {\n name: string;\n nodeKind: NodeKind;\n count: number;\n sum: number | null;\n min: number | null;\n max: number | null;\n}\n\ninterface AggregateDbRow {\n name: string;\n node_kind: string;\n count: number;\n sum: number | null;\n min: number | null;\n max: number | null;\n}\n\ninterface AllStatement<P extends unknown[]> {\n readonly source: string;\n all(...params: P): unknown[];\n}\n\n/** One node's value for one metric, joined to the node's own vocabulary columns. */\nexport interface TopMetricRow {\n nodeId: string;\n name: string;\n kind: string;\n role: string | null;\n value: number | null;\n unit: string | null;\n}\n\ninterface TopMetricDbRow {\n node_id: string;\n value: number | null;\n unit: string | null;\n kind: string;\n name: string;\n role: string | null;\n}\n\nexport interface TargetedStatements {\n listMetricsForNode: AllStatement<[snapshotId: number, nodeId: string]>;\n listEdgesTouching: AllStatement<[{ snapshotId: number; nodeId: string }]>;\n aggregateMetric: AllStatement<[snapshotId: number, name: string]>;\n aggregateMetrics: AllStatement<[snapshotId: number]>;\n listMetricNames: AllStatement<[snapshotId: number]>;\n topByMetric: AllStatement<[snapshotId: number, metric: string, limit: number]>;\n topByMetricOfKind: AllStatement<[snapshotId: number, metric: string, kind: string, limit: number]>;\n}\n\nconst EDGE_COLS = \"src_id, dst_id, kind, attrs\";\n// CROSS JOIN pins metric as the outer loop; unanalyzed, SQLite otherwise probes metric once per node.\nconst AGGREGATE_SELECT = `SELECT m.name AS name, n.kind AS node_kind, COUNT(m.value) AS count,\n SUM(m.value) AS sum, MIN(m.value) AS min, MAX(m.value) AS max\n FROM metric m CROSS JOIN node n ON n.snapshot_id = m.snapshot_id AND n.id = m.node_id`;\nconst TOP_SELECT = `SELECT m.node_id, m.value, m.unit, n.kind, n.name, n.role\n FROM metric m JOIN node n ON n.snapshot_id = m.snapshot_id AND n.id = m.node_id\n WHERE m.snapshot_id = ? AND m.name = ?`;\nconst TOP_ORDER = \"ORDER BY m.value DESC LIMIT ?\";\n\n/** Reads that touch one node or one metric instead of a whole snapshot; each is an index search. */\nexport function prepareTargetedStatements(db: Db): TargetedStatements {\n return {\n listMetricsForNode: db.prepare(\n \"SELECT node_id, name, value, unit FROM metric WHERE snapshot_id = ? AND node_id = ?\",\n ),\n // The second arm skips self-loops so an edge from a node to itself comes back once.\n listEdgesTouching: db.prepare(\n `SELECT ${EDGE_COLS} FROM edge WHERE snapshot_id = @snapshotId AND src_id = @nodeId\n UNION ALL\n SELECT ${EDGE_COLS} FROM edge WHERE snapshot_id = @snapshotId AND dst_id = @nodeId AND src_id <> @nodeId`,\n ),\n aggregateMetric: db.prepare(\n `${AGGREGATE_SELECT} WHERE m.snapshot_id = ? AND m.name = ? GROUP BY n.kind ORDER BY n.kind`,\n ),\n aggregateMetrics: db.prepare(\n `${AGGREGATE_SELECT} WHERE m.snapshot_id = ? GROUP BY m.name, n.kind ORDER BY m.name, n.kind`,\n ),\n listMetricNames: db.prepare(\"SELECT DISTINCT name FROM metric WHERE snapshot_id = ? ORDER BY name\"),\n topByMetric: db.prepare(`${TOP_SELECT} ${TOP_ORDER}`),\n topByMetricOfKind: db.prepare(`${TOP_SELECT} AND n.kind = ? ${TOP_ORDER}`),\n };\n}\n\nexport function readMetricsForNode(stmts: TargetedStatements, snapshotId: number, nodeId: string): GraphMetric[] {\n return (stmts.listMetricsForNode.all(snapshotId, nodeId) as MetricDbRow[]).map(rowToMetric);\n}\n\nexport function readEdgesTouching(stmts: TargetedStatements, snapshotId: number, nodeId: string): GraphEdge[] {\n return (stmts.listEdgesTouching.all({ snapshotId, nodeId }) as EdgeDbRow[]).map(rowToEdge);\n}\n\nexport function readMetricNames(stmts: TargetedStatements, snapshotId: number): string[] {\n return (stmts.listMetricNames.all(snapshotId) as Array<{ name: string }>).map((r) => r.name);\n}\n\nexport function readTopByMetric(\n stmts: TargetedStatements,\n opts: { snapshotId: number; metric: string; limit?: number; kind?: string },\n): TopMetricRow[] {\n const limit = opts.limit ?? 20;\n const rows = (\n opts.kind === undefined\n ? stmts.topByMetric.all(opts.snapshotId, opts.metric, limit)\n : stmts.topByMetricOfKind.all(opts.snapshotId, opts.metric, opts.kind, limit)\n ) as TopMetricDbRow[];\n return rows.map((r) => ({\n nodeId: r.node_id,\n name: r.name,\n kind: r.kind,\n role: r.role,\n value: r.value,\n unit: r.unit,\n }));\n}\n\nexport function readMetricAggregates(stmts: TargetedStatements, snapshotId: number, name?: string): MetricAggregate[] {\n const rows = (\n name === undefined ? stmts.aggregateMetrics.all(snapshotId) : stmts.aggregateMetric.all(snapshotId, name)\n ) as AggregateDbRow[];\n return rows.map((r) => ({\n name: r.name,\n nodeKind: r.node_kind as NodeKind,\n count: r.count,\n sum: r.sum,\n min: r.min,\n max: r.max,\n }));\n}\n","import { SNAPSHOT_SCOPED_TABLES } from \"./schema.js\";\nimport type { CodeGraphStore } from \"./store.js\";\nimport type { SnapshotRow } from \"./types.js\";\n\nexport interface PrunePlan {\n keep: SnapshotRow[];\n remove: SnapshotRow[];\n}\n\nexport interface PruneOptions {\n keep?: number;\n keepRefs?: readonly string[];\n}\n\n// codewatch's list named `boundary` and `entry_point`, which this schema never created.\nconst CASCADE_TABLES = SNAPSHOT_SCOPED_TABLES;\n\nexport function planPrune(store: CodeGraphStore, options: PruneOptions = {}): PrunePlan {\n const keepCount = options.keep ?? 10;\n const keepRefs = new Set(options.keepRefs ?? []);\n const all = store.listSnapshots({ limit: 1_000_000 });\n const keep: SnapshotRow[] = [];\n const remove: SnapshotRow[] = [];\n for (let i = 0; i < all.length; i++) {\n const snap = all[i]!;\n if (i < keepCount || keepRefs.has(snap.ref)) {\n keep.push(snap);\n } else {\n remove.push(snap);\n }\n }\n return { keep, remove };\n}\n\nexport interface PruneResult {\n plan: PrunePlan;\n rowsBefore: Record<string, number>;\n rowsAfter: Record<string, number>;\n vacuumed: boolean;\n}\n\nexport function runPrune(store: CodeGraphStore, options: PruneOptions & { vacuum?: boolean } = {}): PruneResult {\n const plan = planPrune(store, options);\n const tables = [\"snapshot\", ...CASCADE_TABLES];\n const rowsBefore = store.countRowsByTable(tables);\n store.deleteSnapshots(plan.remove.map((s) => s.id));\n if (options.vacuum) store.vacuum();\n const rowsAfter = store.countRowsByTable(tables);\n return { plan, rowsBefore, rowsAfter, vacuumed: !!options.vacuum };\n}\n","import { realpathSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { parseFile, type ParsedFile } from \"@titan-design/code-parser\";\nimport type { CodeGraphStore } from \"./store.js\";\nimport { LanguageExtractor } from \"./extractors/dispatch.js\";\nimport { detectGitHead, detectGitToplevel } from \"./git-renames.js\";\nimport { computeAliasBridge } from \"./identity/index-aliases.js\";\nimport { ALIAS_BASE_ATTR } from \"./identity/lineage.js\";\nimport { annotateRoles, computeRoleHints } from \"./roles.js\";\nimport { walkSourceFiles } from \"./file-walk.js\";\nimport { pruneDanglingReferences } from \"./barrel-resolve.js\";\nimport { fileId } from \"./extractors/ids.js\";\nimport {\n assembleFragments,\n buildFingerprints,\n classifyForReuse,\n classifyParsed,\n loadReuseBasis,\n readSourceFiles,\n} from \"./incremental.js\";\nimport { computeDeltaAffected } from \"./reuse-delta.js\";\nimport { buildIndexerMetrics } from \"./index-metrics.js\";\nimport type { HistoryMetricsOptions } from \"./history-metrics.js\";\nimport { mergeFragments, type ExtractAccumulator } from \"./merge.js\";\nimport { predatesQualifiedSymbols, qualifiedSymbolAliases } from \"./symbol-aliases.js\";\nimport type { GraphMetric, IdAlias } from \"./types.js\";\n\n/**\n * Bumping this invalidates every reuse basis: a snapshot written by a different\n * index version is never reused, so a change to node/edge shape or to a metric's\n * value for the same bytes can never be carried forward from an incompatible graph.\n */\nexport const INDEX_VERSION = \"0.18.0\";\n\n/** The languages walked and extracted. `typescript` covers `.ts` and `.tsx`. */\nconst LANGUAGES = [\"typescript\", \"python\"] as const;\n\nexport interface IndexOptions {\n /** Roots to walk. Node ids are still rooted at the git toplevel, so importers across roots share an id space. */\n paths: string[];\n ref?: string;\n commitHash?: string;\n tsConfig?: string;\n detectRenames?: boolean;\n computeMetrics?: boolean;\n /**\n * Reuse the prior snapshot for byte-identical files: skip their tree-sitter\n * parse + ts-morph extract and carry their nodes/edges/source metrics forward.\n * Defaults to `true`; the reuse path is equivalent to a full index, so the only\n * reason to disable it is to rebuild from scratch.\n */\n incremental?: boolean;\n /** Git churn, recency, and ownership metrics. Defaults to `true`; history is skipped silently outside git. */\n computeChurn?: boolean;\n /** Primary churn window in days (default 30); scopes ownership. */\n churnWindowDays?: number;\n /** Windows to store churn for (default 30, 90, 180); the primary window is always included. */\n churnWindows?: number[];\n /** Also store an all-time `lifetime` churn and ownership window over full git history. */\n lifetime?: boolean;\n}\n\nexport interface IndexResult {\n snapshotId: number;\n files: number;\n nodes: number;\n edges: number;\n aliases: number;\n metrics: number;\n /** Files whose parse + extract were skipped by reusing the prior snapshot. */\n reused: number;\n /** Files parsed + extracted this run (new, changed, or full index). */\n reparsed: number;\n /** Parsed files whose extract was skipped as cosmetic; a subset of `reparsed`. */\n cosmetic: number;\n nodesByKind: Record<string, number>;\n edgesByKind: Record<string, number>;\n}\n\nfunction canonicalizePath(p: string): string {\n try {\n return realpathSync(p);\n } catch {\n return p;\n }\n}\n\nfunction normalizePaths(paths: readonly string[]): string[] {\n if (paths.length === 0) throw new Error(\"indexPaths requires at least one path\");\n return [...new Set(paths.map((p) => path.resolve(p)))];\n}\n\nfunction countByKind<T extends { kind: string }>(items: Iterable<T>): Record<string, number> {\n const out: Record<string, number> = {};\n for (const item of items) out[item.kind] = (out[item.kind] ?? 0) + 1;\n return out;\n}\n\nfunction persist(\n store: CodeGraphStore,\n snapshot: { ref: string; commitHash?: string; aliasBase: number | null },\n accumulator: ExtractAccumulator,\n aliases: readonly IdAlias[],\n metrics: readonly GraphMetric[],\n): number {\n const { ref, commitHash, aliasBase } = snapshot;\n const attrs = { [ALIAS_BASE_ATTR]: aliasBase };\n const snapshotId = store.createSnapshot({ ref, commitHash, indexVersion: INDEX_VERSION, attrs });\n store.insertNodes(snapshotId, [...accumulator.nodes.values()]);\n store.insertEdges(snapshotId, [...accumulator.edges.values()]);\n if (aliases.length > 0) store.insertAliases(snapshotId, aliases);\n if (metrics.length > 0) store.insertMetrics(snapshotId, metrics);\n return snapshotId;\n}\n\n/** Aliases from bare-name symbol ids to qualified ones, when the newest prior snapshot predates them. */\nfunction resolveSymbolAliases(\n store: CodeGraphStore,\n idRoot: string,\n parsedByPath: ReadonlyMap<string, ParsedFile>,\n nodeIds: ReadonlySet<string>,\n): IdAlias[] {\n const prior = store.listSnapshots({ limit: 1 })[0];\n if (!prior || !predatesQualifiedSymbols(prior.indexVersion)) return [];\n const files = [...parsedByPath.values()].map((file) => ({ fileId: fileId(idRoot, file.filePath), file }));\n return qualifiedSymbolAliases(files, nodeIds);\n}\n\n/**\n * Node ids are rooted at the git toplevel so a subtree index shares an id space\n * with a whole-repo one. Inside git, roots are canonicalized to match\n * `git rev-parse --show-toplevel`, which resolves symlinks (`/var` →\n * `/private/var` on macOS); outside git they are left as the caller wrote them.\n */\nfunction resolveRoots(paths: readonly string[]): { rootDirs: string[]; idRoot: string } {\n const raw = normalizePaths(paths);\n const gitToplevel = detectGitToplevel(raw[0]!);\n const rootDirs = gitToplevel !== null ? raw.map(canonicalizePath) : raw;\n return { rootDirs, idRoot: gitToplevel ?? rootDirs[0]! };\n}\n\nasync function parseAll(\n toParse: readonly { filePath: string; content: string; language: string }[],\n): Promise<Map<string, ParsedFile>> {\n const parsed = new Map<string, ParsedFile>();\n for (const rf of toParse) {\n parsed.set(rf.filePath, await parseFile(rf.content, rf.filePath, rf.language));\n }\n return parsed;\n}\n\nfunction historyOptions(options: IndexOptions): HistoryMetricsOptions {\n return {\n churnWindowDays: options.churnWindowDays,\n churnWindows: options.churnWindows,\n includeLifetime: options.lifetime === true,\n };\n}\n\n/**\n * Index one or more roots into a new snapshot: walk, read, parse what changed,\n * extract, annotate roles, compute metrics, and persist. Files unchanged since\n * the prior snapshot are carried forward rather than re-parsed, so the result\n * matches a full index regardless of how much was reused.\n */\nexport async function indexPaths(store: CodeGraphStore, options: IndexOptions): Promise<IndexResult> {\n const { rootDirs, idRoot } = resolveRoots(options.paths);\n const readFiles = await readSourceFiles(await walkSourceFiles(rootDirs, LANGUAGES));\n\n const reuse = options.incremental !== false ? loadReuseBasis(store, INDEX_VERSION) : null;\n const currentFileIds = new Set(readFiles.map((rf) => fileId(idRoot, rf.filePath)));\n // On a file-membership delta, reuse every unchanged file except those whose\n // imports the delta re-resolves; empty when membership is unchanged.\n const affected = reuse ? computeDeltaAffected(reuse, currentFileIds) : new Set<string>();\n const { toParse, reusedFileIds } = classifyForReuse(readFiles, idRoot, reuse, affected);\n\n const parsedByPath = await parseAll(toParse);\n const classified = classifyParsed(parsedByPath, idRoot, reuse, reusedFileIds, affected);\n const accumulator = mergeFragments(\n assembleFragments({\n readFiles,\n idRoot,\n parsedByPath,\n reuse,\n cosmeticFileIds: classified.cosmeticFileIds,\n extractor: new LanguageExtractor({ repoRoot: idRoot, tsConfigPath: options.tsConfig }),\n }),\n );\n const annotated = annotateRoles([...accumulator.nodes.values()], computeRoleHints(readFiles, idRoot, fileId));\n accumulator.nodes = new Map(annotated.map((n) => [n.id, n]));\n pruneDanglingReferences(accumulator.nodes, accumulator.edges);\n\n const metrics =\n options.computeMetrics === false\n ? []\n : buildIndexerMetrics({\n nodes: accumulator.nodes,\n edges: accumulator.edges,\n parsedFiles: [...parsedByPath.values()],\n reusedSourceMetrics: reuse\n ? reusedFileIds.flatMap((id) => reuse.sourceMetricsByFile.get(id) ?? [])\n : [],\n idRoot,\n history: options.computeChurn === false ? undefined : historyOptions(options),\n });\n\n const rootDir = rootDirs[0]!;\n const ref = options.ref ?? \"wd\";\n const bridge = computeAliasBridge(store, { ...options, rootDir, idRoot, ref, nodes: accumulator.nodes });\n const aliases = [\n ...bridge.aliases,\n ...resolveSymbolAliases(store, idRoot, parsedByPath, new Set(accumulator.nodes.keys())),\n ];\n const commitHash = options.commitHash ?? detectGitHead(rootDir) ?? undefined;\n const snapshot = { ref, commitHash, aliasBase: bridge.baseSnapshotId };\n const snapshotId = persist(store, snapshot, accumulator, aliases, metrics);\n store.insertFingerprints(snapshotId, buildFingerprints(readFiles, idRoot, classified.structuralByFileId));\n\n return {\n snapshotId,\n files: readFiles.length,\n nodes: accumulator.nodes.size,\n edges: accumulator.edges.size,\n aliases: aliases.length,\n metrics: metrics.length,\n reused: reusedFileIds.length,\n reparsed: toParse.length,\n cosmetic: classified.cosmeticFileIds.size,\n nodesByKind: countByKind(accumulator.nodes.values()),\n edgesByKind: countByKind(accumulator.edges.values()),\n };\n}\n","import {\n Project,\n ScriptTarget,\n ModuleKind,\n ModuleResolutionKind,\n type ExportDeclaration,\n type ImportDeclaration,\n type SourceFile,\n} from \"ts-morph\";\nimport type { Extractor, ParsedFile } from \"@titan-design/code-parser\";\nimport type { GraphEdge, GraphFragment, GraphNode } from \"../types.js\";\nimport { buildFileModuleNodes } from \"./file-nodes.js\";\nimport { externalId, fileId, symbolId } from \"./ids.js\";\nimport {\n addWeightedEdge,\n bindingWeight,\n buildLocalUsageCounts,\n importWeight,\n namedImportBindings,\n reExportWeight,\n} from \"./reference-weight.js\";\nimport { buildSymbolNodes } from \"./symbol-nodes.js\";\nimport {\n dynamicImportSpecifiers,\n recordDynamicSymbolRefEdges,\n} from \"./dynamic-imports.js\";\nimport { resolveReExportOrigin } from \"./reexport-resolve.js\";\nimport {\n inRepoFileId,\n isRelativeSpecifier,\n remapDistToSrc,\n repoTypeRoots,\n resolveRelativeAbs,\n} from \"./module-resolution.js\";\nimport { collectTsCallEdges } from \"./ts-calls.js\";\n\n/** Mutable accumulator threaded through one file's edge collection. */\ninterface EdgeCollector {\n srcAbs: string;\n srcFileId: string;\n usage: Map<string, number>;\n agg: Map<string, GraphEdge>;\n externalNodes: GraphNode[];\n seenExternals: Set<string>;\n}\n\nexport interface TsMorphGraphExtractorOptions {\n repoRoot: string;\n tsConfigPath?: string;\n project?: Project;\n}\n\nexport class TsMorphGraphExtractor implements Extractor<GraphFragment> {\n readonly name = \"ts-morph-graph\";\n private readonly repoRoot: string;\n private readonly tsConfigPath?: string;\n private project?: Project;\n\n constructor(options: TsMorphGraphExtractorOptions) {\n this.repoRoot = options.repoRoot;\n this.tsConfigPath = options.tsConfigPath;\n this.project = options.project;\n }\n\n extract(file: ParsedFile): GraphFragment[] {\n if (!isTypeScriptFile(file)) return [];\n\n const project = this.ensureProject();\n const sourceFile = this.loadSourceFile(project, file);\n const nodes = this.buildFileAndModuleNodes(sourceFile);\n const symbolNodes = buildSymbolNodes(this.repoRoot, sourceFile, file);\n const { edges, externalNodes } = this.collectEdges(sourceFile);\n const calls = collectTsCallEdges(sourceFile, {\n repoRoot: this.repoRoot,\n srcFileId: fileId(this.repoRoot, sourceFile.getFilePath()),\n localSymbols: new Set(symbolNodes.map((n) => n.name)),\n });\n return [{ nodes: [...nodes, ...symbolNodes, ...externalNodes], edges: [...edges, ...calls] }];\n }\n\n private ensureProject(): Project {\n if (this.project) return this.project;\n this.project = this.tsConfigPath\n ? new Project({ tsConfigFilePath: this.tsConfigPath })\n : new Project({\n compilerOptions: {\n allowJs: true,\n target: ScriptTarget.ESNext,\n module: ModuleKind.ESNext,\n moduleResolution: ModuleResolutionKind.NodeNext,\n typeRoots: repoTypeRoots(this.repoRoot),\n },\n });\n return this.project;\n }\n\n private loadSourceFile(project: Project, file: ParsedFile): SourceFile {\n const existing = project.getSourceFile(file.filePath);\n if (existing) {\n if (existing.getFullText() !== file.content) {\n existing.replaceWithText(file.content);\n }\n return existing;\n }\n return project.createSourceFile(file.filePath, file.content, {\n overwrite: true,\n });\n }\n\n private buildFileAndModuleNodes(sourceFile: SourceFile): GraphNode[] {\n return buildFileModuleNodes(this.repoRoot, sourceFile.getFilePath());\n }\n\n private collectEdges(sourceFile: SourceFile): {\n edges: GraphEdge[];\n externalNodes: GraphNode[];\n } {\n const c: EdgeCollector = {\n srcAbs: sourceFile.getFilePath(),\n srcFileId: fileId(this.repoRoot, sourceFile.getFilePath()),\n usage: buildLocalUsageCounts(sourceFile),\n agg: new Map(),\n externalNodes: [],\n seenExternals: new Set(),\n };\n for (const decl of sourceFile.getImportDeclarations()) {\n this.recordImportEdge(c, decl);\n }\n for (const decl of sourceFile.getExportDeclarations()) {\n this.recordReExportEdge(c, decl);\n }\n for (const specifier of dynamicImportSpecifiers(sourceFile)) {\n const dstId = this.resolveRelativeInternal(c.srcAbs, specifier);\n if (dstId) addWeightedEdge(c.agg, c.srcFileId, dstId, \"imports\", specifier, 1);\n }\n // C-68: destructured dynamic imports (`const { x } = await import(...)`) also\n // credit the target symbol; resolution is delegated so this stays out of the\n // (churn-hot, LOC-bound) extractor body.\n recordDynamicSymbolRefEdges(sourceFile, c.srcFileId, c.agg, (s) =>\n this.resolveRelativeInternal(c.srcAbs, s),\n );\n return { edges: [...c.agg.values()], externalNodes: c.externalNodes };\n }\n\n private recordImportEdge(c: EdgeCollector, decl: ImportDeclaration): void {\n const specifier = decl.getModuleSpecifierValue();\n const dstId = this.resolveTarget(c, specifier, decl);\n if (dstId) {\n addWeightedEdge(c.agg, c.srcFileId, dstId, \"imports\", specifier, importWeight(decl, c.usage));\n }\n this.recordSymbolReferences(c, decl);\n }\n\n /**\n * Split an import into per-export `references` edges targeting `symbol` nodes,\n * so per-symbol utilization (which exports are hot) falls out of the same\n * inbound-weight sum that powers file utilization (C-53). Extracted *forward*\n * from the importing file — source-local, exactly like the file-level import\n * weight — which sidesteps the reuse-breaking reverse `findReferences` query:\n * an unchanged file's outbound reference edges are carried forward verbatim.\n */\n private recordSymbolReferences(c: EdgeCollector, decl: ImportDeclaration): void {\n const specifier = decl.getModuleSpecifierValue();\n for (const binding of namedImportBindings(decl)) {\n const dstId = this.resolveSymbolTarget(c, decl, binding.importedName);\n if (!dstId) continue;\n addWeightedEdge(\n c.agg,\n c.srcFileId,\n dstId,\n \"references\",\n specifier,\n bindingWeight(binding, c.usage),\n );\n }\n }\n\n /**\n * Resolve an imported name to the id of the `symbol` node for the export that\n * actually *declares* it — following re-exports through barrels via ts-morph's\n * own `getExportedDeclarations`, so `import { x } from \"./barrel\"` credits the\n * origin file's `x`, not the barrel. When ts-morph can't resolve the specifier\n * (e.g. an extensionless relative import), falls back to a filesystem-based\n * re-export walk that still sees through barrel hops (C-70). Returns null for\n * external / unresolved targets.\n * A name that resolves to no local declaration (an aliased re-export the\n * origin doesn't export under this name) yields a dangling edge, pruned after\n * assembly (`pruneDanglingReferences`).\n */\n private resolveSymbolTarget(\n c: EdgeCollector,\n decl: ImportDeclaration,\n importedName: string,\n ): string | null {\n const targetSf = decl.getModuleSpecifierSourceFile();\n if (targetSf) {\n const decls = targetSf.getExportedDeclarations().get(importedName);\n const originSf =\n decls && decls.length > 0 ? decls[0]!.getSourceFile() : targetSf;\n const originId = this.inRepoFileId(remapDistToSrc(originSf.getFilePath()));\n return originId ? symbolId(originId, importedName) : null;\n }\n // ts-morph couldn't link the specifier (extensionless / out-of-project);\n // trace the target's re-export hops on disk so an import through an\n // extensionless barrel still credits the origin symbol (C-70).\n return resolveReExportOrigin(\n { project: this.ensureProject(), repoRoot: this.repoRoot },\n c.srcAbs,\n decl.getModuleSpecifierValue(),\n importedName,\n );\n }\n\n private recordReExportEdge(c: EdgeCollector, decl: ExportDeclaration): void {\n if (!decl.hasModuleSpecifier()) return;\n const specifier = decl.getModuleSpecifierValue();\n if (!specifier) return;\n const dstId = this.resolveTarget(c, specifier, decl);\n if (dstId) {\n addWeightedEdge(c.agg, c.srcFileId, dstId, \"re-exports\", specifier, reExportWeight(decl));\n }\n }\n\n /**\n * Resolve an import/export specifier to a graph node id (an in-repo file id or\n * an `external` node, creating the external node on first sight), or `null`\n * when it should not produce an edge.\n */\n private resolveTarget(\n c: EdgeCollector,\n specifier: string,\n decl: ImportDeclaration | ExportDeclaration,\n ): string | null {\n const internal =\n this.resolveInternal(decl.getModuleSpecifierSourceFile()) ??\n this.resolveRelativeInternal(c.srcAbs, specifier);\n if (internal) return internal;\n if (isRelativeSpecifier(specifier)) {\n // A relative import ts-morph could not resolve and that does not point at\n // a file on disk (e.g. an alias, or a genuinely missing target). Dropping\n // it is correct: bucketing it as an npm external produced `npm:..` junk\n // nodes and masked real internal edges for any out-of-project TS (C-44).\n return null;\n }\n const extId = externalId(specifier);\n if (!c.seenExternals.has(extId)) {\n c.seenExternals.add(extId);\n c.externalNodes.push({ id: extId, kind: \"external\", name: specifier });\n }\n return extId;\n }\n\n private resolveInternal(target: SourceFile | undefined): string | null {\n if (!target) return null;\n return this.inRepoFileId(remapDistToSrc(target.getFilePath()));\n }\n\n /**\n * Resolve a relative specifier ts-morph failed to link by walking the\n * filesystem from the importing file. ts-morph's NodeNext resolution only\n * links relative imports that carry an explicit `.js` extension, so\n * extensionless bundler-style imports (`../types`, common in code outside the\n * tsconfig project such as `dashboard/`) resolve to nothing and would\n * otherwise fall through to the `npm:` external bucket (C-44). Resolves\n * through the ts-morph filesystem host so it honours in-memory test fixtures.\n */\n private resolveRelativeInternal(\n srcAbs: string,\n specifier: string,\n ): string | null {\n const abs = resolveRelativeAbs(\n this.ensureProject().getFileSystem(),\n srcAbs,\n specifier,\n );\n return abs ? inRepoFileId(this.repoRoot, abs) : null;\n }\n\n private inRepoFileId(abs: string): string | null {\n return inRepoFileId(this.repoRoot, abs);\n }\n}\n\nfunction isTypeScriptFile(file: ParsedFile): boolean {\n return file.language === \"typescript\" || file.language === \"tsx\";\n}\n","import * as path from \"node:path\";\nimport { getLanguageFromPath } from \"@titan-design/code-parser\";\nimport { fileId, moduleId, parentModuleId } from \"./ids.js\";\nimport type { GraphNode } from \"../types.js\";\n\n/**\n * Build the `file` + `module` nodes for a source file from its path alone.\n * Path-derived and deterministic, so the incremental indexer can reconstruct an\n * unchanged file's nodes without re-parsing it — they are byte-for-byte the same\n * nodes the extractor would emit. Keep this the single source of truth for\n * file/module node shape.\n */\nexport function buildFileModuleNodes(repoRoot: string, absPath: string): GraphNode[] {\n const fId = fileId(repoRoot, absPath);\n const mId = moduleId(repoRoot, absPath);\n const parentId = parentModuleId(mId) ?? undefined;\n const language = getLanguageFromPath(absPath) ?? \"typescript\";\n return [\n { id: fId, kind: \"file\", name: path.basename(fId), parentId: mId, language },\n { id: mId, kind: \"module\", name: path.basename(mId), parentId, language },\n ];\n}\n","import * as path from \"node:path\";\n\nconst MODULE_EXT_RE = /\\.(?:tsx|ts|jsx|js|mts|cts|mjs|cjs|py)$/;\n\nfunction toPosix(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n\nfunction repoRelative(repoRoot: string, absPath: string): string {\n const rel = path.relative(repoRoot, absPath);\n return toPosix(rel);\n}\n\nexport function fileId(repoRoot: string, absPath: string): string {\n return repoRelative(repoRoot, absPath);\n}\n\nexport function moduleId(repoRoot: string, absPath: string): string {\n const rel = repoRelative(repoRoot, absPath);\n return rel.replace(MODULE_EXT_RE, \"\");\n}\n\nexport function parentModuleId(id: string): string | null {\n const idx = id.lastIndexOf(\"/\");\n if (idx < 0) return null;\n return id.slice(0, idx);\n}\n\nexport function packageId(name: string): string {\n return name;\n}\n\n// Symbol nodes hang under their declaring file: `<fileId>#<qualifiedName>` (C-53),\n// where a member carries its enclosing scopes, `Job.run` (TP-182).\n// `#` never occurs in a posix path or a JS export identifier, so it can't\n// collide with a real file id — and it is printable, unlike the NUL separators\n// that made git treat files as binary (C-21).\nexport const SYMBOL_ID_SEP = \"#\";\n\nexport function symbolId(fileId: string, qualifiedName: string): string {\n return `${fileId}${SYMBOL_ID_SEP}${qualifiedName}`;\n}\n\n/**\n * Inverse of {@link symbolId}: split a `<fileId>#<name>` symbol id back into its\n * declaring file and qualified name. Returns null for an id with no separator (a\n * plain file id), so callers can filter the symbol layer cleanly. `#` is illegal\n * in both posix paths and JS identifiers, so the first occurrence is the split.\n */\nexport function parseSymbolId(\n id: string,\n): { fileId: string; name: string } | null {\n const idx = id.indexOf(SYMBOL_ID_SEP);\n if (idx < 0) return null;\n return { fileId: id.slice(0, idx), name: id.slice(idx + 1) };\n}\n\nexport function externalId(specifier: string): string {\n if (specifier.startsWith(\"node:\")) {\n return specifier;\n }\n return `npm:${bareName(specifier)}`;\n}\n\nfunction bareName(specifier: string): string {\n if (specifier.startsWith(\"@\")) {\n const parts = specifier.split(\"/\");\n return parts.slice(0, 2).join(\"/\");\n }\n const slash = specifier.indexOf(\"/\");\n return slash < 0 ? specifier : specifier.slice(0, slash);\n}\n","import {\n Node,\n SyntaxKind,\n type ExportDeclaration,\n type Identifier,\n type ImportDeclaration,\n type SourceFile,\n} from \"ts-morph\";\nimport type { EdgeKind, GraphEdge } from \"../types.js\";\n\n/**\n * Reference-count edge weighting (C-51). File-level import/re-export edges carry\n * a `weight` on `attrs` measuring how heavily the source file leans on the\n * target — not merely whether it imports from it. A file that calls one imported\n * helper 30× is more coupled than one that names 30 helpers once; a binary edge\n * cannot tell them apart. Everything here is source-local (it reads only the\n * importing file's text), so the weight stays sound under incremental reuse,\n * which reparses a file only when its own content changes.\n */\n\n/**\n * Fold a specifier into the aggregate, summing weights so parallel imports of\n * one module (e.g. a value import plus a type import) collapse to a single\n * edge whose weight is their combined reference count.\n */\nexport function addWeightedEdge(\n agg: Map<string, GraphEdge>,\n srcId: string,\n dstId: string,\n kind: EdgeKind,\n specifier: string,\n weight: number,\n): void {\n const key = JSON.stringify([kind, dstId]);\n const existing = agg.get(key);\n if (existing) {\n (existing.attrs as { weight: number }).weight += weight;\n return;\n }\n agg.set(key, { srcId, dstId, kind, attrs: { specifier, weight } });\n}\n\n/**\n * How many times the importing file actually uses the symbols it brings in,\n * floored at 1 so a live-but-unused import (or a `import \"./x\"` side-effect\n * import, which binds nothing) still reads as a real dependency.\n */\nexport function importWeight(\n decl: ImportDeclaration,\n usage: Map<string, number>,\n): number {\n const names = importBindingNames(decl);\n if (names.length === 0) return 1; // side-effect import: `import \"./x\"`\n const used = names.reduce((sum, n) => sum + (usage.get(n) ?? 0), 0);\n return Math.max(used, 1);\n}\n\n/**\n * One named or default import binding, pairing the name as *exported by the\n * target module* (what a symbol node is keyed on) with the *local* alias in\n * this file (what usage counts key on). Namespace imports (`import * as ns`)\n * are deliberately excluded: they reference the module as a whole, not any one\n * export, so per-symbol attribution isn't well-defined — the file-level\n * `imports` edge still accounts for them (C-53).\n */\nexport interface ImportBinding {\n importedName: string;\n localName: string;\n}\n\nexport function namedImportBindings(decl: ImportDeclaration): ImportBinding[] {\n const out: ImportBinding[] = [];\n const def = decl.getDefaultImport();\n if (def) out.push({ importedName: \"default\", localName: def.getText() });\n for (const spec of decl.getNamedImports()) {\n out.push({\n importedName: spec.getNameNode().getText(),\n localName: (spec.getAliasNode() ?? spec.getNameNode()).getText(),\n });\n }\n return out;\n}\n\n/**\n * Per-binding reference weight: how many times this file uses the imported\n * symbol, floored at 1 so a named-but-only-referenced-once import still reads\n * as a real dependency (naming a symbol is itself a use).\n */\nexport function bindingWeight(\n binding: ImportBinding,\n usage: Map<string, number>,\n): number {\n return Math.max(usage.get(binding.localName) ?? 0, 1);\n}\n\nfunction importBindingNames(decl: ImportDeclaration): string[] {\n const names: string[] = [];\n const def = decl.getDefaultImport();\n if (def) names.push(def.getText());\n const ns = decl.getNamespaceImport();\n if (ns) names.push(ns.getText());\n for (const spec of decl.getNamedImports()) {\n names.push((spec.getAliasNode() ?? spec.getNameNode()).getText());\n }\n return names;\n}\n\n/**\n * Re-export edges have no local usage to count — the names pass straight\n * through — so weight them by how many names cross the boundary: the count of\n * re-exported specifiers, or 1 for `export * from`.\n */\nexport function reExportWeight(decl: ExportDeclaration): number {\n if (decl.isNamespaceExport()) return 1;\n return Math.max(decl.getNamedExports().length, 1);\n}\n\n/**\n * Count identifier occurrences per name across the file in a single pass,\n * skipping the import/export declarations themselves and property *name*\n * positions (`obj.foo`, `{ foo: … }`) — those name a member, not a reference to\n * an imported binding. Binding names are unique per file (TS forbids\n * redeclaration), so a name's total attributes cleanly to one edge. Local\n * shadowing (a variable reusing an imported name) can over-count; acceptable\n * for a coupling-strength signal.\n */\nexport function buildLocalUsageCounts(\n sourceFile: SourceFile,\n): Map<string, number> {\n const counts = new Map<string, number>();\n for (const id of sourceFile.getDescendantsOfKind(SyntaxKind.Identifier)) {\n if (id.getFirstAncestorByKind(SyntaxKind.ImportDeclaration)) continue;\n if (id.getFirstAncestorByKind(SyntaxKind.ExportDeclaration)) continue;\n if (isPropertyNamePosition(id)) continue;\n const text = id.getText();\n counts.set(text, (counts.get(text) ?? 0) + 1);\n }\n return counts;\n}\n\nfunction isPropertyNamePosition(id: Identifier): boolean {\n const parent = id.getParent();\n if (Node.isPropertyAccessExpression(parent) && parent.getNameNode() === id) {\n return true;\n }\n if (Node.isPropertyAssignment(parent) && parent.getNameNode() === id) {\n return true;\n }\n return false;\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/** Declarations that name the scope they open. */\nconst TS_NAMED_SCOPES = new Set([\n \"class_declaration\",\n \"abstract_class_declaration\",\n \"class\",\n \"function_declaration\",\n \"generator_function_declaration\",\n \"method_definition\",\n \"internal_module\",\n]);\n\n/** Values that take the name they are bound to, or open an anonymous scope when unbound. */\nconst TS_BOUND_SCOPES = new Set([\n \"class\",\n \"arrow_function\",\n \"function_expression\",\n \"generator_function\",\n \"object\",\n]);\n\nconst PY_NAMED_SCOPES = new Set([\"function_definition\", \"class_definition\"]);\n\n/** The segment an unbound callback, object or class adds, so its members never merge with a named declaration. */\nexport const ANONYMOUS_SCOPE = \"<anonymous>\";\n\n/** Join an enclosing scope path and a declared name into the dotted name a symbol id carries. */\nexport function qualify(scope: string, name: string): string {\n return scope ? `${scope}.${name}` : name;\n}\n\n/**\n * The name a value is bound to: `const x = …`, a class field `x = …`, an object\n * key `x: …`, or `default` for `export default`. Null for a value passed as an\n * argument or returned, which has no stable name.\n */\nfunction bindingName(node: Node): string | null {\n const parent = node.parent;\n if (!parent) return null;\n if (parent.type === \"variable_declarator\" || parent.type === \"public_field_definition\") {\n return parent.childForFieldName(\"name\")?.text ?? null;\n }\n if (parent.type === \"pair\") return parent.childForFieldName(\"key\")?.text ?? null;\n if (parent.type === \"export_statement\") return \"default\";\n return null;\n}\n\n/** The segment this node adds to its descendants' scope path, or null when it opens no named scope. */\nfunction scopeSegment(node: Node, python: boolean): string | null {\n if (python) {\n return PY_NAMED_SCOPES.has(node.type) ? (node.childForFieldName(\"name\")?.text ?? null) : null;\n }\n const own = TS_NAMED_SCOPES.has(node.type) ? node.childForFieldName(\"name\")?.text : undefined;\n if (own) return own;\n if (!TS_BOUND_SCOPES.has(node.type)) return null;\n return bindingName(node) ?? ANONYMOUS_SCOPE;\n}\n\n/** Consecutive anonymous scopes collapse to one segment: nesting depth is not identity. */\nfunction enter(scope: string, segment: string | null): string {\n if (!segment) return scope;\n if (segment === ANONYMOUS_SCOPE && (scope === ANONYMOUS_SCOPE || scope.endsWith(`.${ANONYMOUS_SCOPE}`))) {\n return scope;\n }\n return qualify(scope, segment);\n}\n\n/**\n * Depth-first walk handing every node the dotted path of the scopes that\n * enclose it (`Job` for a method of `class Job`, `outer` for a function nested\n * in `outer`). A callback argument or an unbound object or class adds\n * `<anonymous>` rather than a position, so the path stays stable when\n * declarations are reordered.\n */\nexport function walkScopes(\n root: Node,\n python: boolean,\n visit: (node: Node, scope: string) => void,\n): void {\n const step = (node: Node, scope: string): void => {\n visit(node, scope);\n const inner = enter(scope, scopeSegment(node, python));\n for (const child of node.children) {\n if (child) step(child, inner);\n }\n };\n step(root, \"\");\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport { qualify, walkScopes } from \"./scope-path.js\";\n\nconst TS_DECL_TYPES = new Set([\n \"function_declaration\",\n \"method_definition\",\n \"class_declaration\",\n]);\n\nconst PY_DECL_TYPES = new Set([\"function_definition\", \"class_definition\"]);\n\n/** 1-based inclusive line span of a declaration, for coverage range-attribution (C-63). */\nexport interface LineSpan {\n startLine: number;\n endLine: number;\n}\n\n/** One declaration: its own name, its scope-qualified name, and its line span. */\nexport interface Declaration {\n name: string;\n qualifiedName: string;\n span: LineSpan;\n}\n\n/**\n * Every function/method/class a file DECLARES, in source order (the model-B\n * symbol surface, C-64). A superset of the file's exports: internal helpers like\n * `mergeFragments` are included so they get a `symbol` node (and their\n * complexity + coverage) even though nothing imports them. Names come from the\n * same tree-sitter walk that computes complexity, so they never drift.\n * `qualifiedName` prefixes the enclosing named scopes (`Job.run`, `outer.inner`)\n * so same-named members of different classes or functions stay apart (TP-182).\n * Anonymous declarations (a default-exported arrow, inline callbacks) are skipped.\n */\nexport function collectDeclarations(file: ParsedFile): Declaration[] {\n const out: Declaration[] = [];\n forEachDeclaration(file, (name, qualifiedName, node) => {\n out.push({\n name,\n qualifiedName,\n span: { startLine: node.startPosition.row + 1, endLine: node.endPosition.row + 1 },\n });\n });\n return out;\n}\n\n/** Visit each declaration's name, scope-qualified name and the node its span and parameters come from. */\nexport function forEachDeclaration(\n file: ParsedFile,\n visit: (name: string, qualifiedName: string, node: Node) => void,\n): void {\n const python = file.language === \"python\";\n const declTypes = python ? PY_DECL_TYPES : TS_DECL_TYPES;\n walkScopes(file.tree.rootNode, python, (node, scope) => {\n const named = declaredNodeAt(node, declTypes);\n if (named) visit(named.name, qualify(scope, named.name), named.node);\n });\n}\n\n/**\n * Qualified declared names mapped to their 1-based line span (C-63 coverage\n * range-containment). One scope binds a name once, as TypeScript and Python do,\n * so a getter/setter pair, a Python property's accessors, and `@overload` stubs\n * share one entry; when a qualified name repeats, the last span wins.\n */\nexport function collectDeclaredSpans(file: ParsedFile): Map<string, LineSpan> {\n const spans = new Map<string, LineSpan>();\n for (const d of collectDeclarations(file)) spans.set(d.qualifiedName, d.span);\n return spans;\n}\n\n/** Declared names only — the Set view over {@link collectDeclaredSpans}. */\nexport function collectDeclaredNames(file: ParsedFile): Set<string> {\n return new Set(collectDeclaredSpans(file).keys());\n}\n\n/**\n * The declaration at this node — its name plus the node whose line span\n * represents it — or null. Mirrors source-metrics' `functionAt` handling of an\n * arrow / function-expression bound to a `const`/`let` (the span is the callable\n * body's node, so it contains the coverage `fnMap` loc), extended to classes.\n */\nfunction declaredNodeAt(\n node: Node,\n declTypes: ReadonlySet<string>,\n): { name: string; node: Node } | null {\n if (declTypes.has(node.type)) {\n const name = node.childForFieldName(\"name\")?.text;\n return name ? { name, node } : null;\n }\n if (\n (node.type === \"arrow_function\" || node.type === \"function_expression\") &&\n node.parent?.type === \"variable_declarator\"\n ) {\n const name = node.parent.childForFieldName(\"name\")?.text;\n return name ? { name, node } : null;\n }\n return null;\n}\n","import type { GraphEdge } from \"../types.js\";\n\n/**\n * The arguments at one resolved call site (TP-323). `args` holds each positional\n * argument's literal text, or null when it is not a literal. `spreadFrom` is the\n * index of the first `...xs` / `*xs`, after which positions are unknown; `kwargs`\n * and `kwSplat` are Python's keyword arguments and `**kw`.\n */\nexport interface CallSite {\n args: (string | null)[];\n kwargs?: Record<string, string | null>;\n spreadFrom?: number;\n kwSplat?: true;\n}\n\n/**\n * A callable's parameters, stored on its symbol node as `params` and `positionalParams`.\n * `params` excludes `this`, a Python method's receiver, and rest or `**kw` parameters;\n * the first `positional` of them can be passed by position, the rest only by keyword.\n */\nexport interface ParamShape {\n params: string[];\n positional: number;\n}\n\n/** Attrs a `calls` edge carries: every site where the caller calls the callee. */\nexport interface CallEdgeAttrs {\n sites: CallSite[];\n}\n\n/** One `calls` edge per caller and callee pair, with every call site appended to it. */\nexport function addCallSite(\n agg: Map<string, GraphEdge>,\n srcId: string,\n dstId: string,\n site: CallSite,\n): void {\n const key = JSON.stringify([srcId, dstId]);\n const existing = agg.get(key);\n if (existing) (existing.attrs as unknown as CallEdgeAttrs).sites.push(site);\n else agg.set(key, { srcId, dstId, kind: \"calls\", attrs: { sites: [site] } });\n}\n\n/** Symbol-node attrs for a shape; `positionalParams` is written only when some parameter is keyword-only. */\nexport function paramAttrs(shape: ParamShape | undefined): Record<string, unknown> {\n if (!shape) return {};\n return shape.positional === shape.params.length\n ? { params: shape.params }\n : { params: shape.params, positionalParams: shape.positional };\n}\n\n/** Read a shape back off a symbol node's attrs, or undefined for a node that is not a callable. */\nexport function readParamShape(attrs: Record<string, unknown> | undefined): ParamShape | undefined {\n const params = attrs?.params;\n if (!Array.isArray(params)) return undefined;\n const positional = typeof attrs?.positionalParams === \"number\" ? attrs.positionalParams : params.length;\n return { params: params as string[], positional };\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport { forEachDeclaration } from \"../declared-names.js\";\nimport type { ParamShape } from \"./call-sites.js\";\n\nconst TS_PARAM_TYPES = new Set([\"required_parameter\", \"optional_parameter\"]);\n\n/**\n * The parameter shape of every function and method a file declares, keyed by\n * qualified name. Classes carry none. From the same tree-sitter walk as the symbol\n * nodes, so a reused file's shapes ride forward on its symbol nodes unchanged.\n */\nexport function collectParamShapes(file: ParsedFile): Map<string, ParamShape> {\n const out = new Map<string, ParamShape>();\n forEachDeclaration(file, (_name, qualifiedName, node) => {\n const shape = file.language === \"python\" ? pythonShape(node) : tsShape(node);\n if (shape) out.set(qualifiedName, shape);\n });\n return out;\n}\n\nfunction tsShape(fn: Node): ParamShape | null {\n if (fn.type === \"class_declaration\") return null;\n const single = fn.childForFieldName(\"parameter\");\n if (single) return { params: [single.text], positional: 1 };\n const params: string[] = [];\n for (const param of fn.childForFieldName(\"parameters\")?.namedChildren ?? []) {\n if (!param || !TS_PARAM_TYPES.has(param.type)) continue;\n const pattern = param.childForFieldName(\"pattern\");\n if (!pattern || pattern.type === \"this\") continue;\n if (pattern.type === \"rest_pattern\") break;\n params.push(pattern.type === \"identifier\" ? pattern.text : `$${params.length}`);\n }\n return { params, positional: params.length };\n}\n\nfunction pythonShape(fn: Node): ParamShape | null {\n if (fn.type !== \"function_definition\") return null;\n const names: string[] = [];\n let positionalEnd: number | null = null;\n for (const param of fn.childForFieldName(\"parameters\")?.namedChildren ?? []) {\n if (!param) continue;\n if (param.type === \"keyword_separator\" || param.type === \"list_splat_pattern\") positionalEnd ??= names.length;\n const name = pythonParamName(param);\n if (name) names.push(name);\n }\n const receiver = hasReceiver(fn) && names.length > 0 ? 1 : 0;\n return { params: names.slice(receiver), positional: Math.max((positionalEnd ?? names.length) - receiver, 0) };\n}\n\n/** The bound name of a plain, typed or defaulted parameter; null for separators and `*args` / `**kw`. */\nfunction pythonParamName(param: Node): string | null {\n if (param.type === \"identifier\") return param.text;\n if (param.type === \"default_parameter\" || param.type === \"typed_default_parameter\") {\n return param.childForFieldName(\"name\")?.text ?? null;\n }\n if (param.type === \"typed_parameter\") {\n const first = param.namedChildren[0];\n return first?.type === \"identifier\" ? first.text : null;\n }\n return null;\n}\n\n/** A method defined directly in a class body takes `self` or `cls` first, unless it is a `@staticmethod`. */\nexport function hasReceiver(fn: Node): boolean {\n const decorated = fn.parent?.type === \"decorated_definition\" ? fn.parent : null;\n const block = (decorated ?? fn).parent;\n if (block?.type !== \"block\" || block.parent?.type !== \"class_definition\") return false;\n const decorators = decorated?.namedChildren.filter((c) => c?.type === \"decorator\") ?? [];\n return !decorators.some((d) => d?.text === \"@staticmethod\");\n}\n","import {\n Node,\n type ArrowFunction,\n type FunctionDeclaration,\n type FunctionExpression,\n type MethodDeclaration,\n type SourceFile,\n type VariableDeclaration,\n} from \"ts-morph\";\n\n/**\n * Persisted qualitative facts about a declaration (C-79): the one-line type\n * `signature` and the leading docstring `purpose`, so `graph context` can answer\n * \"what is this and how is it called\" without the reader opening the file — the\n * G1/G2 gap the C-74 spike found vs brain's codebase module.\n *\n * Both are pure syntactic projections of the declaration (params + explicit\n * return annotation + JSDoc), so an unchanged file's symbol nodes stay\n * byte-identical and the incremental indexer carries them forward. Inferred\n * types are only used when they carry no `import(\"…\")` module path — those embed\n * absolute paths that are non-deterministic and reuse-breaking.\n */\nexport interface SymbolText {\n signature?: string;\n purpose?: string;\n}\n\nconst MAX_SIGNATURE = 200;\nconst MAX_PURPOSE = 240;\n\ntype Callable =\n | FunctionDeclaration\n | MethodDeclaration\n | ArrowFunction\n | FunctionExpression;\n\n/** Signature + docstring for a ts-morph declaration node, best-effort. */\nexport function declarationText(decl: Node): SymbolText {\n const out: SymbolText = {};\n const signature = signatureOf(decl);\n if (signature) out.signature = signature;\n const purpose = purposeOf(decl);\n if (purpose) out.purpose = purpose;\n return out;\n}\n\n/**\n * The file-level declaration named `name`, for the non-exported symbol surface\n * (model B, C-64) where only the name + tree-sitter span is known. Class methods\n * are not addressable by file-level name, so they resolve to undefined (no\n * signature) — acceptable, the exported API is the primary target.\n */\nexport function lookupDeclaration(\n sf: SourceFile,\n name: string,\n): Node | undefined {\n return (\n sf.getFunction(name) ??\n sf.getClass(name) ??\n sf.getInterface(name) ??\n sf.getTypeAlias(name) ??\n sf.getEnum(name) ??\n sf.getVariableDeclaration(name)\n );\n}\n\nfunction signatureOf(decl: Node): string | undefined {\n if (Node.isFunctionDeclaration(decl) || Node.isMethodDeclaration(decl)) {\n return callableSignature(decl, decl.getName() ?? \"\");\n }\n if (Node.isVariableDeclaration(decl)) return variableSignature(decl);\n if (Node.isClassDeclaration(decl)) return clamp(`class ${decl.getName() ?? \"\"}`.trim());\n if (Node.isInterfaceDeclaration(decl)) return clamp(`interface ${decl.getName()}`);\n if (Node.isTypeAliasDeclaration(decl)) {\n return clamp(`type ${decl.getName()} = ${oneLine(decl.getTypeNode()?.getText() ?? \"\")}`);\n }\n if (Node.isEnumDeclaration(decl)) return clamp(`enum ${decl.getName()}`);\n return undefined;\n}\n\nfunction variableSignature(decl: VariableDeclaration): string | undefined {\n const init = decl.getInitializer();\n if (init && (Node.isArrowFunction(init) || Node.isFunctionExpression(init))) {\n return callableSignature(init, decl.getName());\n }\n const typeNode = decl.getTypeNode();\n const type = typeNode ? oneLine(typeNode.getText()) : cleanType(() => decl.getType().getText());\n return type ? clamp(`${decl.getName()}: ${type}`) : undefined;\n}\n\nfunction callableSignature(decl: Callable, name: string): string {\n const params = decl.getParameters().map((p) => oneLine(p.getText())).join(\", \");\n const ret = returnType(decl);\n return clamp(`${name}(${params})${ret ? `: ${ret}` : \"\"}`);\n}\n\nfunction returnType(decl: Callable): string | undefined {\n const node = decl.getReturnTypeNode();\n if (node) return oneLine(node.getText());\n return cleanType(() => decl.getReturnType().getText());\n}\n\n/**\n * Inferred type text, but only when it carries no `import(\"…\")` module path\n * (those embed absolute paths → non-deterministic + reuse-breaking). Returns\n * undefined rather than a dirty type, so the signature simply omits it.\n */\nfunction cleanType(getText: () => string): string | undefined {\n let text: string;\n try {\n text = getText();\n } catch {\n return undefined;\n }\n if (!text || text.includes(\"import(\")) return undefined;\n return oneLine(text);\n}\n\nfunction purposeOf(decl: Node): string | undefined {\n const docs = jsDocsFor(decl);\n if (!docs || docs.length === 0) return undefined;\n const desc = docs[docs.length - 1]!.getDescription().trim();\n return desc ? clamp(oneLine(desc), MAX_PURPOSE) : undefined;\n}\n\nfunction jsDocsFor(decl: Node) {\n if (Node.isJSDocable(decl)) return decl.getJsDocs();\n if (Node.isVariableDeclaration(decl)) return decl.getVariableStatement()?.getJsDocs();\n return undefined;\n}\n\nfunction oneLine(s: string): string {\n return s.replace(/\\s+/g, \" \").trim();\n}\n\nfunction clamp(s: string, max = MAX_SIGNATURE): string {\n return s.length > max ? `${s.slice(0, max - 1)}…` : s;\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { SourceFile } from \"ts-morph\";\nimport { collectDeclaredSpans, type LineSpan } from \"../declared-names.js\";\nimport { fileId, symbolId } from \"./ids.js\";\nimport { paramAttrs, type ParamShape } from \"./call-sites.js\";\nimport { collectParamShapes } from \"./callable-params.js\";\nimport { declarationText, lookupDeclaration, type SymbolText } from \"./symbol-signature.js\";\nimport type { GraphNode } from \"../types.js\";\n\n/**\n * A `symbol` node for a declaration, tagging whether it is exported (C-64) and,\n * when it is a function/method/class, its 1-based line span (C-63) so coverage\n * can be attributed by range containment. A span-less symbol (an exported type or\n * const value) just carries `exported`. When ts-morph resolves the declaration it\n * also carries a one-line `signature` and docstring `purpose` (C-79) — both\n * omitted (not stored as null) when unavailable, so attrs stay byte-identical for\n * incremental reuse.\n */\nfunction makeSymbolNode(\n fileId: string,\n name: string,\n exported: boolean,\n span: LineSpan | undefined,\n text: SymbolText,\n shape: ParamShape | undefined,\n): GraphNode {\n const attrs: Record<string, unknown> = { exported, ...paramAttrs(shape) };\n if (span) {\n attrs.startLine = span.startLine;\n attrs.endLine = span.endLine;\n }\n if (text.signature) attrs.signature = text.signature;\n if (text.purpose) attrs.purpose = text.purpose;\n return {\n id: symbolId(fileId, name),\n kind: \"symbol\",\n name,\n parentId: fileId,\n language: \"typescript\",\n attrs,\n };\n}\n\n/**\n * A `symbol` node per declaration a file owns (model B, C-64). Two sources, both\n * source-local so an unchanged file's symbol nodes are byte-identical across runs\n * and the incremental indexer carries them forward without re-parsing:\n *\n * - **Exported declarations** (`exported: true`) — from ts-morph's\n * `getExportedDeclarations`, which barrel-resolves. Names this file merely\n * re-exports are skipped: they belong to the origin file's symbol nodes, so\n * `references` edges resolved through a barrel land on the file that does the\n * work, not the hub (C-53 / C-55). Covers functions, classes, types, and\n * exported const values alike — the reference-edge targets.\n * - **Non-exported functions / methods / classes** (`exported: false`) — from the\n * tree-sitter declared-name walk (same parser as complexity), so an internal\n * helper like `mergeFragments` gets a node and, by name match, its own\n * complexity, closing the C-59 Dossier gap. Internal *non-callable* bindings\n * (plain const values) are intentionally excluded — only functions/methods/\n * classes.\n */\nexport function buildSymbolNodes(\n repoRoot: string,\n sourceFile: SourceFile,\n file: ParsedFile,\n): GraphNode[] {\n const fId = fileId(repoRoot, sourceFile.getFilePath());\n const spans = collectDeclaredSpans(file);\n const shapes = collectParamShapes(file);\n const out: GraphNode[] = [];\n const exported = new Set<string>();\n for (const [name, decls] of sourceFile.getExportedDeclarations()) {\n const own = decls.find((d) => d.getSourceFile() === sourceFile);\n if (!own) continue;\n exported.add(name);\n out.push(makeSymbolNode(fId, name, true, spans.get(name), declarationText(own), shapes.get(name)));\n }\n for (const [name, span] of spans) {\n if (exported.has(name)) continue;\n const decl = lookupDeclaration(sourceFile, name);\n out.push(makeSymbolNode(fId, name, false, span, decl ? declarationText(decl) : {}, shapes.get(name)));\n }\n return out;\n}\n","import {\n Node,\n SyntaxKind,\n type ObjectBindingPattern,\n type SourceFile,\n} from \"ts-morph\";\nimport type { GraphEdge } from \"../types.js\";\nimport { symbolId } from \"./ids.js\";\nimport { addWeightedEdge } from \"./reference-weight.js\";\n\n/**\n * String-literal specifiers of dynamic `import(\"…\")` expressions in a file\n * (C-65). The static import graph only records `import`/`export` *declarations*,\n * so a module loaded lazily — e.g. `cli/src/index.ts` doing\n * `import(\"./commands/analyze.js\")` to register a command — otherwise has no\n * inbound edge and reads `fan_in` 0, falsely appearing dead. Capturing these\n * closes that blind spot for the common case.\n *\n * Only string-literal specifiers are returned; a computed specifier\n * (`import(variable)`) is genuinely unresolvable statically and is left out (a\n * documented blind spot, same class as DI/registry-string wiring).\n */\nexport function dynamicImportSpecifiers(sourceFile: SourceFile): string[] {\n const out: string[] = [];\n for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {\n if (call.getExpression().getKind() !== SyntaxKind.ImportKeyword) continue;\n const arg = call.getArguments()[0];\n if (arg && arg.getKind() === SyntaxKind.StringLiteral) {\n out.push(arg.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralText());\n }\n }\n return out;\n}\n\n/** One export pulled out of a destructured dynamic import. */\ninterface DynamicImportBinding {\n specifier: string;\n /** The name as exported by the target module (property name, not local alias). */\n importedName: string;\n}\n\n/**\n * Destructured bindings of a dynamic import — `const { runX } = await import(\"…\")`\n * — pairing each pulled-out export with its target module (C-68). This is the\n * lazy-command-loading pattern (the CLI registers a subcommand via\n * `const { runX } = await import(\"./x.js\")`); C-65 captured only the module\n * edge, so the target's export still read as unused despite being live. Emitting\n * a per-symbol `references` edge from these clears that dead-code false positive.\n *\n * Only object destructuring binds a specific export. `const ns = await import(…)`\n * (namespace) and `.then(m => m.x)` are excluded — the module `imports` edge\n * already accounts for the whole-module dependency, exactly as a static\n * namespace import is handled (C-53). The property name (not the local alias) is\n * returned, matching how a `symbol` node is keyed.\n */\nfunction dynamicImportBindings(\n sourceFile: SourceFile,\n): DynamicImportBinding[] {\n const out: DynamicImportBinding[] = [];\n for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {\n if (call.getExpression().getKind() !== SyntaxKind.ImportKeyword) continue;\n const arg = call.getArguments()[0];\n if (!arg || arg.getKind() !== SyntaxKind.StringLiteral) continue;\n const pattern = destructuredTargetOf(call);\n if (!pattern) continue;\n const specifier = arg.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralText();\n for (const importedName of destructuredNames(pattern)) {\n out.push({ specifier, importedName });\n }\n }\n return out;\n}\n\n/**\n * The object-binding pattern a dynamic `import()` call feeds, if the call is the\n * initializer of a `const { … } = (await) import(…)` declaration. Returns\n * undefined for a namespace binding, a `.then()` chain, or any non-initializer\n * position — those don't destructure a specific export.\n */\nfunction destructuredTargetOf(call: Node): ObjectBindingPattern | undefined {\n const parent = call.getParent();\n if (!parent) return undefined;\n const init = Node.isAwaitExpression(parent) ? parent : call;\n const decl = init.getParent();\n if (!decl || !Node.isVariableDeclaration(decl)) return undefined;\n if (decl.getInitializer() !== init) return undefined;\n const nameNode = decl.getNameNode();\n return Node.isObjectBindingPattern(nameNode) ? nameNode : undefined;\n}\n\n/**\n * Exported names bound by an object pattern: `{ runX }` → `runX`,\n * `{ runX: local }` → `runX` (the exported name, not the alias). A rest element\n * (`{ ...rest }`) binds no single export and is skipped.\n */\nfunction destructuredNames(pattern: ObjectBindingPattern): string[] {\n const names: string[] = [];\n for (const el of pattern.getElements()) {\n if (el.getDotDotDotToken()) continue;\n const nameNode = el.getPropertyNameNode() ?? el.getNameNode();\n names.push(nameNode.getText());\n }\n return names;\n}\n\n/**\n * Add a `references` edge (importer → target symbol) for each destructured\n * dynamic import in a file (C-68). Kept here rather than in the extractor class\n * so the churn-hot, LOC-bound extractor body stays minimal; specifier→file\n * resolution is delegated to the caller (it needs the ts-morph project's\n * filesystem host). A target the module doesn't export dangles and is pruned\n * after assembly (`pruneDanglingReferences`).\n */\nexport function recordDynamicSymbolRefEdges(\n sourceFile: SourceFile,\n srcFileId: string,\n agg: Map<string, GraphEdge>,\n resolveSpecifier: (specifier: string) => string | null,\n): void {\n for (const binding of dynamicImportBindings(sourceFile)) {\n const targetFileId = resolveSpecifier(binding.specifier);\n if (!targetFileId) continue;\n addWeightedEdge(\n agg,\n srcFileId,\n symbolId(targetFileId, binding.importedName),\n \"references\",\n binding.specifier,\n 1,\n );\n }\n}\n","import * as path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport type { FileSystemHost } from \"ts-morph\";\nimport { fileId } from \"./ids.js\";\n\n/** Source/compiled extensions a relative specifier may resolve to, in priority order. */\nexport const RESOLVABLE_EXTS = [\n \".ts\",\n \".tsx\",\n \".mts\",\n \".cts\",\n \".js\",\n \".jsx\",\n \".mjs\",\n \".cjs\",\n];\n\nexport function isRelativeSpecifier(specifier: string): boolean {\n return (\n specifier === \".\" ||\n specifier === \"..\" ||\n specifier.startsWith(\"./\") ||\n specifier.startsWith(\"../\")\n );\n}\n\n/**\n * Candidate on-disk paths for a resolved relative import base, in priority\n * order: an explicit extension already present, then the source extensions,\n * then a NodeNext `.js`→`.ts` remap, then `index.*` for directory imports.\n */\nexport function* relativeResolutionCandidates(base: string): Iterable<string> {\n yield base;\n for (const ext of RESOLVABLE_EXTS) yield base + ext;\n const jsExt = /\\.(?:jsx?|mjs|cjs)$/.exec(base);\n if (jsExt) {\n const stem = base.slice(0, base.length - jsExt[0].length);\n for (const ext of RESOLVABLE_EXTS) yield stem + ext;\n }\n for (const ext of RESOLVABLE_EXTS) yield path.join(base, \"index\" + ext);\n}\n\n/**\n * Resolve a relative specifier from a file to an on-disk absolute path via the\n * ts-morph filesystem host (honours in-memory test fixtures), or null. ts-morph's\n * NodeNext resolution only links relative imports carrying an explicit `.js`\n * extension, so extensionless bundler-style imports (`../types`, common outside\n * the tsconfig project) need this fallback (C-44).\n */\nexport function resolveRelativeAbs(\n fs: FileSystemHost,\n fromAbs: string,\n specifier: string,\n): string | null {\n if (!isRelativeSpecifier(specifier)) return null;\n const base = path.resolve(path.dirname(fromAbs), specifier);\n for (const candidate of relativeResolutionCandidates(base)) {\n if (fs.fileExistsSync(candidate)) return candidate;\n }\n return null;\n}\n\n/** Map an abs path to an in-repo file id, or null if out of tree / in node_modules. */\nexport function inRepoFileId(repoRoot: string, abs: string): string | null {\n const relative = path.relative(repoRoot, abs);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) return null;\n if (relative.split(path.sep).includes(\"node_modules\")) return null;\n return fileId(repoRoot, abs);\n}\n\n// ts-morph resolves workspace imports like `@codewatch/analyzer` to the\n// package's `types` entry (`<pkg>/dist/index.d.ts`), but the indexer's file\n// walker excludes `dist/` and `.d.ts`. Without remapping, every cross-package\n// edge points to a nonexistent node and the rendered graph fails to construct.\nexport function remapDistToSrc(abs: string): string {\n const m = /^(.*)[\\\\/]dist[\\\\/](.+)\\.d\\.ts$/.exec(abs);\n if (!m) return abs;\n const base = m[1]!;\n const sub = m[2]!;\n for (const ext of [\".ts\", \".tsx\"]) {\n const candidate = path.join(base, \"src\", sub + ext);\n if (existsSync(candidate)) return candidate;\n }\n return abs;\n}\n\n/**\n * `node_modules/@types` dirs from `repoRoot` up to the filesystem root: TypeScript's\n * default type-root walk, anchored at the indexed repo instead of `process.cwd()`.\n */\nexport function repoTypeRoots(repoRoot: string): string[] {\n const roots: string[] = [];\n for (let dir = path.resolve(repoRoot); ; dir = path.dirname(dir)) {\n roots.push(path.join(dir, \"node_modules\", \"@types\"));\n if (path.dirname(dir) === dir) return roots;\n }\n}\n","import type { ExportDeclaration, Project, SourceFile } from \"ts-morph\";\nimport { symbolId } from \"./ids.js\";\nimport { inRepoFileId, resolveRelativeAbs } from \"./module-resolution.js\";\n\n/** Context the re-export walk needs: the ts-morph project and the repo root. */\nexport interface ReExportCtx {\n project: Project;\n repoRoot: string;\n}\n\n/**\n * Trace an imported name to the id of the `symbol` node for the export that\n * physically DECLARES it, walking re-export hops on disk (C-70). ts-morph's own\n * `getExportedDeclarations` already sees through barrels whose specifiers it can\n * resolve; this covers the case it can't — extensionless / out-of-project\n * relative specifiers (the tRPC pattern) — by resolving `specifier` from\n * `importerAbs` and following `export { x } from './b'` and `export * from './b'`\n * hops by hand. Returns null (→ a dangling edge, pruned after assembly) when the\n * name is neither declared here nor forwarded onward.\n */\nexport function resolveReExportOrigin(\n ctx: ReExportCtx,\n importerAbs: string,\n specifier: string,\n name: string,\n): string | null {\n const fs = ctx.project.getFileSystem();\n const targetAbs = resolveRelativeAbs(fs, importerAbs, specifier);\n return targetAbs ? walkReExports(ctx, targetAbs, name, new Set()) : null;\n}\n\nfunction walkReExports(\n ctx: ReExportCtx,\n fileAbs: string,\n name: string,\n visited: Set<string>,\n): string | null {\n if (visited.has(fileAbs)) return null;\n visited.add(fileAbs);\n // The indexer adds files to the project one at a time as it extracts them, so\n // a barrel/origin file on this walk may not be loaded yet — pull it from the\n // filesystem host on demand (cached thereafter).\n const sf =\n ctx.project.getSourceFile(fileAbs) ??\n ctx.project.addSourceFileAtPathIfExists(fileAbs);\n if (!sf) return null;\n if (declaresExportLocally(sf, name)) {\n const id = inRepoFileId(ctx.repoRoot, fileAbs);\n return id ? symbolId(id, name) : null;\n }\n const fs = ctx.project.getFileSystem();\n for (const ed of sf.getExportDeclarations()) {\n const spec = ed.getModuleSpecifierValue();\n if (!spec) continue;\n const inward = reExportInwardName(ed, name);\n if (inward === null) continue;\n const targetAbs = resolveRelativeAbs(fs, fileAbs, spec);\n if (!targetAbs) continue;\n const origin = walkReExports(ctx, targetAbs, inward, visited);\n if (origin) return origin;\n }\n return null;\n}\n\n/**\n * Whether `sf` physically declares an export named `name` — the same test\n * `buildSymbolNodes` uses to decide a name is this file's own symbol, so a\n * re-export walk that stops here lands on a symbol node that actually exists.\n */\nfunction declaresExportLocally(sf: SourceFile, name: string): boolean {\n const decls = sf.getExportedDeclarations().get(name);\n return !!decls && decls.some((d) => d.getSourceFile() === sf);\n}\n\n/**\n * For a re-export `export ... from '...'`, the name to look up in the target\n * module when the outward name is `name`, or null if this declaration does not\n * forward `name`.\n * - `export { a as b } from '...'` forwards outward `b` ← inward `a`.\n * - `export * from '...'` forwards every name unchanged.\n * - `export * as ns from '...'` binds a namespace object, not member names, so\n * it never forwards an individual `name` (we don't attribute per-member).\n */\nfunction reExportInwardName(ed: ExportDeclaration, name: string): string | null {\n const named = ed.getNamedExports();\n if (named.length > 0) {\n for (const spec of named) {\n const outward = spec.getAliasNode()?.getText() ?? spec.getName();\n if (outward === name) return spec.getName();\n }\n return null;\n }\n if (ed.getNamespaceExport()) return null; // `export * as ns from`\n return name; // bare `export *`\n}\n","import { Node, SyntaxKind, type CallExpression, type NewExpression, type SourceFile } from \"ts-morph\";\nimport type { GraphEdge } from \"../types.js\";\nimport { addCallSite, type CallSite } from \"./call-sites.js\";\nimport { symbolId } from \"./ids.js\";\nimport { inRepoFileId, remapDistToSrc } from \"./module-resolution.js\";\nimport { declarationQualifiedName } from \"./ts-scope.js\";\n\nexport interface TsCallContext {\n srcFileId: string;\n /** Qualified names this file has symbol nodes for; a caller must be one of them. */\n localSymbols: ReadonlySet<string>;\n repoRoot: string;\n}\n\ntype Call = CallExpression | NewExpression;\n\n/**\n * `calls` edges from each call or `new` in a file to the in-repo symbol the type\n * checker resolves its callee to (TP-323). The caller is the nearest enclosing\n * declaration with a symbol node, or the file for a top-level call. A callee the\n * checker cannot resolve to exactly one in-repo declaration is dropped.\n */\nexport function collectTsCallEdges(sourceFile: SourceFile, ctx: TsCallContext): GraphEdge[] {\n const agg = new Map<string, GraphEdge>();\n sourceFile.forEachDescendant((node) => {\n if (!Node.isCallExpression(node) && !Node.isNewExpression(node)) return;\n const dstId = resolveCallee(node, ctx);\n if (dstId) addCallSite(agg, callerId(node, ctx), dstId, tsCallSite(node));\n });\n return [...agg.values()];\n}\n\nfunction resolveCallee(call: Call, ctx: TsCallContext): string | null {\n const callee = call.getExpression();\n if (callee.getKind() === SyntaxKind.SuperKeyword) return null;\n const symbol = callee.getSymbol();\n if (!symbol) return null;\n const target = symbol.isAlias() ? symbol.getAliasedSymbol() : symbol;\n const ids = new Set<string>();\n for (const decl of target?.getDeclarations() ?? []) {\n const id = declarationId(decl, ctx);\n if (id === null) return null;\n ids.add(id);\n }\n return ids.size === 1 ? [...ids][0]! : null;\n}\n\nfunction declarationId(decl: Node, ctx: TsCallContext): string | null {\n const sf = decl.getSourceFile();\n const abs = remapDistToSrc(sf.getFilePath());\n if (sf.isDeclarationFile() && abs === sf.getFilePath()) return null;\n const fileId = inRepoFileId(ctx.repoRoot, abs);\n const name = fileId ? declarationQualifiedName(decl) : null;\n return fileId && name ? symbolId(fileId, name) : null;\n}\n\nfunction callerId(call: Call, ctx: TsCallContext): string {\n for (const ancestor of call.getAncestors()) {\n const name = declarationQualifiedName(ancestor);\n if (name && ctx.localSymbols.has(name)) return symbolId(ctx.srcFileId, name);\n }\n return ctx.srcFileId;\n}\n\nfunction tsCallSite(call: Call): CallSite {\n const site: CallSite = { args: [] };\n for (const arg of call.getArguments()) {\n if (Node.isSpreadElement(arg)) {\n site.spreadFrom ??= site.args.length;\n break;\n }\n site.args.push(literalText(arg));\n }\n return site;\n}\n\nconst LITERAL_KINDS = new Set([\n SyntaxKind.NumericLiteral,\n SyntaxKind.StringLiteral,\n SyntaxKind.NoSubstitutionTemplateLiteral,\n SyntaxKind.TrueKeyword,\n SyntaxKind.FalseKeyword,\n SyntaxKind.NullKeyword,\n]);\n\n/** The source text of a literal argument (a negative number included), else null. */\nfunction literalText(arg: Node): string | null {\n if (LITERAL_KINDS.has(arg.getKind())) return arg.getText();\n if (Node.isIdentifier(arg) && arg.getText() === \"undefined\") return \"undefined\";\n if (Node.isPrefixUnaryExpression(arg) && arg.getOperatorToken() === SyntaxKind.MinusToken) {\n return Node.isNumericLiteral(arg.getOperand()) ? arg.getText() : null;\n }\n return null;\n}\n","import { Node } from \"ts-morph\";\nimport { ANONYMOUS_SCOPE, qualify } from \"../scope-path.js\";\n\n/**\n * The ts-morph mirror of `scope-path.ts`: the scope-qualified name tree-sitter\n * gives a declaration, computed from a ts-morph node so a declaration the type\n * checker resolves in any file maps onto that file's symbol id (TP-323). A name\n * the two walks disagree on yields an id with no symbol node, and the edge is\n * pruned, never misattributed.\n */\n\n/** The name a value takes from what it is bound to, as `bindingName` in scope-path.ts; null when unbound. */\nfunction bindingName(node: Node): string | null {\n const parent = node.getParent();\n if (Node.isVariableDeclaration(parent) || Node.isPropertyDeclaration(parent)) return parent.getName();\n if (Node.isPropertyAssignment(parent)) return parent.getNameNode().getText();\n if (Node.isExportAssignment(parent)) return \"default\";\n return null;\n}\n\n/** A class or function declaration's own name, or `default` for an unnamed default export. */\nfunction declaredName(node: Node & { getName(): string | undefined }): string | null {\n const name = node.getName();\n if (name) return name;\n return Node.isExportable(node) && node.isDefaultExport() ? \"default\" : null;\n}\n\n/** The segment a node adds to the scope of its descendants, or null when it opens no named scope. */\nfunction scopeSegment(node: Node): string | null {\n if (Node.isClassDeclaration(node) || Node.isFunctionDeclaration(node)) return declaredName(node);\n if (Node.isMethodDeclaration(node) || Node.isGetAccessorDeclaration(node) || Node.isSetAccessorDeclaration(node)) {\n return node.getName();\n }\n if (Node.isConstructorDeclaration(node)) return \"constructor\";\n if (Node.isModuleDeclaration(node)) return node.hasNamespaceKeyword() ? node.getName() : null;\n if (Node.isClassExpression(node) && node.getName()) return node.getName() ?? null;\n const bound =\n Node.isArrowFunction(node) ||\n Node.isFunctionExpression(node) ||\n Node.isClassExpression(node) ||\n Node.isObjectLiteralExpression(node);\n return bound ? (bindingName(node) ?? ANONYMOUS_SCOPE) : null;\n}\n\n/** The dotted scope path enclosing `node`, collapsing consecutive anonymous segments. */\nexport function scopeOf(node: Node): string {\n const segments = node\n .getAncestors()\n .map(scopeSegment)\n .filter((s): s is string => s !== null)\n .reverse();\n let scope = \"\";\n for (const segment of segments) {\n const repeatsAnonymous =\n segment === ANONYMOUS_SCOPE && (scope === ANONYMOUS_SCOPE || scope.endsWith(`.${ANONYMOUS_SCOPE}`));\n if (!repeatsAnonymous) scope = qualify(scope, segment);\n }\n return scope;\n}\n\n/**\n * The qualified name of a declaration that has a symbol node: a function,\n * method, accessor, constructor or class, or a variable bound to an arrow or\n * function expression. Null for anything else (a parameter, an interface member).\n */\nexport function declarationQualifiedName(decl: Node): string | null {\n if (Node.isVariableDeclaration(decl)) {\n const init = decl.getInitializer();\n const callable = Node.isArrowFunction(init) || Node.isFunctionExpression(init);\n return callable ? qualify(scopeOf(decl), decl.getName()) : null;\n }\n if (Node.isArrowFunction(decl) || Node.isFunctionExpression(decl)) {\n const parent = decl.getParent();\n return Node.isVariableDeclaration(parent) ? qualify(scopeOf(parent), parent.getName()) : null;\n }\n const isDeclaration =\n Node.isFunctionDeclaration(decl) ||\n Node.isClassDeclaration(decl) ||\n Node.isMethodDeclaration(decl) ||\n Node.isGetAccessorDeclaration(decl) ||\n Node.isSetAccessorDeclaration(decl) ||\n Node.isConstructorDeclaration(decl);\n const own = isDeclaration ? scopeSegment(decl) : null;\n return own ? qualify(scopeOf(decl), own) : null;\n}\n","import * as path from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport type { Node } from \"web-tree-sitter\";\nimport type { Extractor, ParsedFile } from \"@titan-design/code-parser\";\nimport { collectDeclaredSpans } from \"../declared-names.js\";\nimport { buildFileModuleNodes } from \"./file-nodes.js\";\nimport { paramAttrs } from \"./call-sites.js\";\nimport { collectParamShapes } from \"./callable-params.js\";\nimport { collectPythonCallEdges } from \"./python-calls.js\";\nimport { externalId, fileId, symbolId } from \"./ids.js\";\nimport { inRepoFileId } from \"./module-resolution.js\";\nimport type { GraphEdge, GraphFragment, GraphNode } from \"../types.js\";\n\n/** `.py` candidates a dotted module path may resolve to, package `__init__` included. */\nfunction* candidates(base: string): Iterable<string> {\n yield `${base}.py`;\n yield path.join(base, \"__init__.py\");\n}\n\n/**\n * Tree-sitter Python extraction. Deliberately narrower than the ts-morph side:\n * no type checker, so imports resolve by dotted path against the tree rather\n * than by symbol resolution, and symbols are the declarations the same\n * tree-sitter walk already finds for complexity. Enough to place Python files in\n * the graph with their dependencies; a semantic Python layer is a follow-up.\n */\nexport class PythonGraphExtractor implements Extractor<GraphFragment> {\n readonly name = \"python-graph\";\n\n constructor(private readonly repoRoot: string) {}\n\n extract(file: ParsedFile): GraphFragment[] {\n if (file.language !== \"python\") return [];\n const fId = fileId(this.repoRoot, file.filePath);\n const nodes = buildFileModuleNodes(this.repoRoot, file.filePath);\n nodes.push(...symbolNodes(fId, file));\n const { edges, externals } = this.collectImports(fId, file);\n const calls = collectPythonCallEdges(file, fId, (specifier) => this.resolveDotted(file.filePath, specifier));\n return [{ nodes: [...nodes, ...externals], edges: [...edges, ...calls] }];\n }\n\n private collectImports(\n srcId: string,\n file: ParsedFile,\n ): { edges: GraphEdge[]; externals: GraphNode[] } {\n const edges = new Map<string, GraphEdge>();\n const externals: GraphNode[] = [];\n for (const specifier of importSpecifiers(file.tree.rootNode)) {\n const internal = this.resolveDotted(file.filePath, specifier);\n const dstId = internal ?? externalId(specifier);\n if (!internal && !edges.has(dstId)) {\n externals.push({ id: dstId, kind: \"external\", name: specifier });\n }\n edges.set(dstId, { srcId, dstId, kind: \"imports\", attrs: { specifier, weight: 1 } });\n }\n return { edges: [...edges.values()], externals };\n }\n\n /**\n * Resolve `a.b.c` (or a leading-dot relative import) to an in-repo file id by\n * walking the dotted path from the importing file's package and then from the\n * repo root, which covers both intra-package and root-relative layouts.\n */\n private resolveDotted(fromAbs: string, specifier: string): string | null {\n const leadingDots = /^\\.*/.exec(specifier)?.[0].length ?? 0;\n const parts = specifier.slice(leadingDots).split(\".\").filter(Boolean);\n const relativeBase = path.resolve(path.dirname(fromAbs), \"../\".repeat(Math.max(leadingDots - 1, 0)));\n const roots = leadingDots > 0 ? [relativeBase] : [path.dirname(fromAbs), this.repoRoot];\n for (const root of roots) {\n for (const candidate of candidates(path.join(root, ...parts))) {\n const id = inRepoFileId(this.repoRoot, candidate);\n if (id !== null && existsSync(candidate)) return id;\n }\n }\n return null;\n }\n}\n\n/** Python identifiers hold no dot, so the last segment of a qualified name is the declared name. */\nfunction isPublicName(qualifiedName: string): boolean {\n return !qualifiedName.slice(qualifiedName.lastIndexOf(\".\") + 1).startsWith(\"_\");\n}\n\nfunction symbolNodes(fId: string, file: ParsedFile): GraphNode[] {\n const shapes = collectParamShapes(file);\n return [...collectDeclaredSpans(file)].map(([name, span]) => ({\n id: symbolId(fId, name),\n kind: \"symbol\" as const,\n name,\n parentId: fId,\n language: \"python\",\n attrs: {\n exported: isPublicName(name),\n startLine: span.startLine,\n endLine: span.endLine,\n ...paramAttrs(shapes.get(name)),\n },\n }));\n}\n\n/** Every module named by an `import x` / `from x import y` statement, in tree order. */\nfunction importSpecifiers(root: Node): string[] {\n const out: string[] = [];\n const visit = (node: Node): void => {\n if (node.type === \"import_statement\" || node.type === \"import_from_statement\") {\n const name = node.childForFieldName(\"module_name\");\n if (name) out.push(name.text);\n else for (const child of node.namedChildren) if (child?.type === \"dotted_name\") out.push(child.text);\n }\n for (const child of node.namedChildren) if (child) visit(child);\n };\n visit(root);\n return out;\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport { forEachDeclaration } from \"../declared-names.js\";\nimport { walkScopes } from \"../scope-path.js\";\nimport type { GraphEdge } from \"../types.js\";\nimport { addCallSite, type CallSite } from \"./call-sites.js\";\nimport { hasReceiver } from \"./callable-params.js\";\nimport { symbolId } from \"./ids.js\";\n\n/** Resolves a dotted module name, relative or absolute, from this file to an in-repo file id. */\nexport type ResolveModule = (specifier: string) => string | null;\n\ninterface PyCallContext {\n fileId: string;\n declarations: Map<string, Node>;\n imports: Map<string, { fileId: string; name: string }>;\n}\n\n/**\n * `calls` edges for the Python calls that resolve without a type checker\n * (TP-323): a bare name declared at module level in this file, a bare name bound\n * by `from <in-repo module> import <name>`, and `self.<name>(...)` to a method of\n * the enclosing class. Attribute chains, `module.func`, star imports and names a\n * parameter or nested def shadows are dropped. The caller is the enclosing def\n * or class, or the file for a module-level call.\n */\nexport function collectPythonCallEdges(file: ParsedFile, fileId: string, resolve: ResolveModule): GraphEdge[] {\n const declarations = new Map<string, Node>();\n forEachDeclaration(file, (_name, qualifiedName, node) => declarations.set(qualifiedName, node));\n const ctx: PyCallContext = { fileId, declarations, imports: fromImports(file.tree.rootNode, resolve) };\n const agg = new Map<string, GraphEdge>();\n walkScopes(file.tree.rootNode, true, (node, scope) => {\n if (node.type !== \"call\") return;\n const dst = resolveCallee(node.childForFieldName(\"function\"), scope, ctx);\n const args = node.childForFieldName(\"arguments\");\n if (!dst || args?.type !== \"argument_list\") return;\n const srcId = declarations.has(scope) ? symbolId(fileId, scope) : fileId;\n addCallSite(agg, srcId, dst, pythonCallSite(args));\n });\n return [...agg.values()];\n}\n\nfunction resolveCallee(callee: Node | null, scope: string, ctx: PyCallContext): string | null {\n if (callee?.type === \"identifier\") return resolveBareName(callee.text, scope, ctx);\n if (callee?.type === \"attribute\") return resolveSelfMethod(callee, scope, ctx);\n return null;\n}\n\nfunction resolveBareName(name: string, scope: string, ctx: PyCallContext): string | null {\n if (isShadowed(name, scope, ctx)) return null;\n const local = ctx.declarations.has(name);\n const imported = ctx.imports.get(name);\n if (local && imported) return null;\n if (local) return symbolId(ctx.fileId, name);\n return imported ? symbolId(imported.fileId, imported.name) : null;\n}\n\n/** True when a scope enclosing the call declares `name` as a nested def or class, or binds it as a parameter. */\nfunction isShadowed(name: string, scope: string, ctx: PyCallContext): boolean {\n const segments = scope ? scope.split(\".\") : [];\n for (let depth = segments.length; depth > 0; depth--) {\n const enclosing = segments.slice(0, depth).join(\".\");\n if (ctx.declarations.has(`${enclosing}.${name}`)) return true;\n if (parameterNames(ctx.declarations.get(enclosing)).includes(name)) return true;\n }\n return false;\n}\n\n/**\n * `self.name(...)` inside a method of class `C`: the def `name` on `C`, or else on\n * the first of `C`'s bases declared in this file that has it, depth first. The\n * receiver is the method's first parameter. A base from another file ends the search.\n */\nfunction resolveSelfMethod(callee: Node, scope: string, ctx: PyCallContext): string | null {\n const receiver = callee.childForFieldName(\"object\");\n const attr = callee.childForFieldName(\"attribute\")?.text;\n const method = ctx.declarations.get(scope);\n if (receiver?.type !== \"identifier\" || !attr || !method || !hasReceiver(method)) return null;\n if (parameterNames(method)[0] !== receiver.text) return null;\n const owner = findMethodOwner(scope.slice(0, scope.lastIndexOf(\".\")), attr, ctx, new Set());\n return owner ? symbolId(ctx.fileId, `${owner}.${attr}`) : null;\n}\n\nfunction findMethodOwner(className: string, attr: string, ctx: PyCallContext, seen: Set<string>): string | null {\n const cls = ctx.declarations.get(className);\n if (cls?.type !== \"class_definition\" || seen.has(className)) return null;\n seen.add(className);\n if (ctx.declarations.get(`${className}.${attr}`)?.type === \"function_definition\") return className;\n for (const base of cls.childForFieldName(\"superclasses\")?.namedChildren ?? []) {\n if (base?.type !== \"identifier\" || !ctx.declarations.has(base.text)) return null;\n const owner = findMethodOwner(base.text, attr, ctx, seen);\n if (owner) return owner;\n }\n return null;\n}\n\n/** Every parameter name of a def, receiver and `*args` / `**kw` included; empty for a class or nothing. */\nfunction parameterNames(def: Node | undefined): string[] {\n if (def?.type !== \"function_definition\") return [];\n const out: string[] = [];\n for (const param of def.childForFieldName(\"parameters\")?.namedChildren ?? []) {\n const id = param?.type === \"identifier\" ? param : param?.descendantsOfType(\"identifier\")[0];\n if (id) out.push(id.text);\n }\n return out;\n}\n\n/** Local names bound by `from <module> import <name> [as <alias>]` whose module resolves in-repo. */\nfunction fromImports(root: Node, resolve: ResolveModule): PyCallContext[\"imports\"] {\n const out: PyCallContext[\"imports\"] = new Map();\n for (const stmt of root.descendantsOfType(\"import_from_statement\")) {\n const moduleName = stmt?.childForFieldName(\"module_name\")?.text;\n const moduleFile = moduleName ? resolve(moduleName) : null;\n if (!stmt || !moduleFile) continue;\n for (const imported of stmt.childrenForFieldName(\"name\")) {\n const alias = imported?.type === \"aliased_import\" ? imported.childForFieldName(\"alias\")?.text : undefined;\n const name = imported?.type === \"aliased_import\" ? imported.childForFieldName(\"name\")?.text : imported?.text;\n if (name && !name.includes(\".\")) out.set(alias ?? name, { fileId: moduleFile, name });\n }\n }\n return out;\n}\n\nconst LITERAL_TYPES = new Set([\"integer\", \"float\", \"true\", \"false\", \"none\"]);\n\n/** The source text of a literal argument; an f-string or a concatenation is not one. */\nfunction literalText(arg: Node): string | null {\n if (LITERAL_TYPES.has(arg.type)) return arg.text;\n if (arg.type === \"string\") return arg.namedChildren.some((c) => c?.type === \"interpolation\") ? null : arg.text;\n if (arg.type === \"unary_operator\" && arg.text.startsWith(\"-\")) {\n const operand = arg.childForFieldName(\"argument\");\n return operand && (operand.type === \"integer\" || operand.type === \"float\") ? arg.text : null;\n }\n return null;\n}\n\nfunction pythonCallSite(argumentList: Node): CallSite {\n const site: CallSite = { args: [] };\n for (const arg of argumentList.namedChildren) {\n if (!arg || arg.type === \"comment\") continue;\n if (arg.type === \"list_splat\") site.spreadFrom ??= site.args.length;\n else if (arg.type === \"dictionary_splat\") site.kwSplat = true;\n else if (arg.type === \"keyword_argument\") addKeyword(site, arg);\n else if (site.spreadFrom === undefined) site.args.push(literalText(arg));\n }\n return site;\n}\n\nfunction addKeyword(site: CallSite, arg: Node): void {\n const name = arg.childForFieldName(\"name\")?.text;\n const value = arg.childForFieldName(\"value\");\n if (!name || !value) return;\n site.kwargs ??= {};\n site.kwargs[name] = literalText(value);\n}\n","import type { Extractor, ParsedFile } from \"@titan-design/code-parser\";\nimport { TsMorphGraphExtractor } from \"./ts-morph-extractor.js\";\nimport { PythonGraphExtractor } from \"./python-extractor.js\";\nimport type { GraphFragment } from \"../types.js\";\n\nexport interface LanguageExtractorOptions {\n repoRoot: string;\n tsConfigPath?: string;\n}\n\n/**\n * One extractor over every supported language: each delegate already returns an\n * empty fragment list for files it does not own, so dispatch is a fold. Keeps\n * `assembleFragments` language-agnostic.\n */\nexport class LanguageExtractor implements Extractor<GraphFragment> {\n readonly name = \"language-graph\";\n private readonly delegates: Extractor<GraphFragment>[];\n\n constructor(options: LanguageExtractorOptions) {\n this.delegates = [\n new TsMorphGraphExtractor({ repoRoot: options.repoRoot, tsConfigPath: options.tsConfigPath }),\n new PythonGraphExtractor(options.repoRoot),\n ];\n }\n\n extract(file: ParsedFile): GraphFragment[] {\n return this.delegates.flatMap((delegate) => delegate.extract(file));\n }\n}\n","import * as path from \"node:path\";\nimport { detectGitToplevel, runGit } from \"./history/git.js\";\nimport { fileId, moduleId } from \"./extractors/ids.js\";\nimport type { IdAlias, IdAliasReason } from \"./types.js\";\n\nexport interface RenamePair {\n oldPath: string;\n newPath: string;\n similarity: number;\n}\n\nexport interface DetectRenamesOptions {\n repoRoot: string;\n fromCommit: string;\n toCommit?: string;\n similarityThreshold?: number;\n}\n\nexport function detectGitHead(repoRoot: string): string | null {\n return runGit(repoRoot, [\"rev-parse\", \"HEAD\"]);\n}\n\nexport function isInsideGitRepo(repoRoot: string): boolean {\n return runGit(repoRoot, [\"rev-parse\", \"--is-inside-work-tree\"]) === \"true\";\n}\n\nexport { detectGitToplevel };\n\n/** Resolve a ref (branch, tag, sha) to its current commit sha, or null. */\nexport function resolveGitRef(repoRoot: string, ref: string): string | null {\n return runGit(repoRoot, [\"rev-parse\", ref]);\n}\n\n/** Whether `ancestor` is reachable from `descendant`; false when either is unknown to the repo. */\nexport function isGitAncestor(repoRoot: string, ancestor: string, descendant: string): boolean {\n return runGit(repoRoot, [\"merge-base\", \"--is-ancestor\", ancestor, descendant]) !== null;\n}\n\nexport function detectRenames(\n options: DetectRenamesOptions,\n): RenamePair[] {\n const threshold = options.similarityThreshold ?? 80;\n const args = [\n \"diff\",\n `--find-renames=${threshold}%`,\n \"--name-status\",\n options.fromCommit,\n ];\n if (options.toCommit) args.push(options.toCommit);\n\n const out = runGit(options.repoRoot, args);\n if (out === null) return [];\n return parseRenameOutput(out);\n}\n\nexport function parseRenameOutput(text: string): RenamePair[] {\n const out: RenamePair[] = [];\n for (const rawLine of text.split(\"\\n\")) {\n const line = rawLine.trimEnd();\n if (!line) continue;\n const parts = line.split(\"\\t\");\n const status = parts[0] ?? \"\";\n if (!status.startsWith(\"R\") || parts.length < 3) continue;\n const similarity = parseInt(status.slice(1), 10);\n out.push({\n oldPath: parts[1]!,\n newPath: parts[2]!,\n similarity: Number.isFinite(similarity) ? similarity : 100,\n });\n }\n return out;\n}\n\nexport function classifyRename(\n oldPath: string,\n newPath: string,\n): IdAliasReason {\n return path.posix.dirname(oldPath) === path.posix.dirname(newPath)\n ? \"rename\"\n : \"move\";\n}\n\nexport function renameToAliases(\n repoRoot: string,\n pair: RenamePair,\n): IdAlias[] {\n const reason = classifyRename(pair.oldPath, pair.newPath);\n const oldAbs = path.join(repoRoot, pair.oldPath);\n const newAbs = path.join(repoRoot, pair.newPath);\n return [\n { oldId: fileId(repoRoot, oldAbs), newId: fileId(repoRoot, newAbs), reason },\n { oldId: moduleId(repoRoot, oldAbs), newId: moduleId(repoRoot, newAbs), reason },\n ];\n}\n\nexport function buildAliases(\n repoRoot: string,\n pairs: readonly RenamePair[],\n): IdAlias[] {\n const seen = new Set<string>();\n const out: IdAlias[] = [];\n for (const pair of pairs) {\n for (const alias of renameToAliases(repoRoot, pair)) {\n if (seen.has(alias.oldId)) continue;\n seen.add(alias.oldId);\n out.push(alias);\n }\n }\n return out;\n}\n","import type { SnapshotRow } from \"../types.js\";\n\n/** Snapshot attrs key naming the snapshot its id aliases were computed against; written from index version 0.15.0. */\nexport const ALIAS_BASE_ATTR = \"aliasBase\";\n\n/** Walks stop after this many snapshots, so a corrupt or enormous lineage cannot run away. */\nexport const DEFAULT_MAX_HOPS = 10_000;\n\nexport type LineageSnapshot = Pick<SnapshotRow, \"id\" | \"commitHash\" | \"attrs\">;\n\n/** Each snapshot's alias base, or null for a root: the tree the id_alias rows form across snapshots. */\nexport type Lineage = ReadonlyMap<number, number | null>;\n\nexport interface LineageStep {\n snapshotId: number;\n /** `forward` applies the snapshot's aliases (base to snapshot); `backward` undoes them. */\n direction: \"forward\" | \"backward\";\n}\n\nfunction recordedBase(snap: LineageSnapshot): number | null | undefined {\n if (!(ALIAS_BASE_ATTR in snap.attrs)) return undefined;\n const base = snap.attrs[ALIAS_BASE_ATTR];\n // Only an earlier snapshot can be a base, which keeps the lineage acyclic.\n return typeof base === \"number\" && base < snap.id ? base : null;\n}\n\n/**\n * The recorded base per snapshot. A snapshot written before 0.15.0 records none,\n * so it gets the newest earlier snapshot with a commit: the one the indexer diffed against then.\n */\nexport function buildLineage(snapshots: readonly LineageSnapshot[]): Lineage {\n const out = new Map<number, number | null>();\n let lastWithCommit: number | null = null;\n for (const snap of [...snapshots].sort((a, b) => a.id - b.id)) {\n const recorded = recordedBase(snap);\n out.set(snap.id, recorded === undefined ? lastWithCommit : recorded);\n if (snap.commitHash) lastWithCommit = snap.id;\n }\n return out;\n}\n\n/** The snapshot followed by its bases up to the root, newest first; `maxHops` bounds a hand-built lineage with a cycle. */\nexport function ancestry(lineage: Lineage, snapshotId: number, maxHops = DEFAULT_MAX_HOPS): number[] {\n const out: number[] = [];\n let current: number | null | undefined = snapshotId;\n while (current !== null && current !== undefined && out.length <= maxHops) {\n out.push(current);\n current = lineage.get(current);\n }\n return out;\n}\n\n/** Steps from one snapshot to another through their nearest common base, or null when they share none. */\nexport function lineagePath(\n lineage: Lineage,\n fromId: number,\n toId: number,\n maxHops = DEFAULT_MAX_HOPS,\n): LineageStep[] | null {\n const up = ancestry(lineage, fromId, maxHops);\n const down = ancestry(lineage, toId, maxHops);\n const upIndex = new Map(up.map((id, i) => [id, i]));\n const meet = down.findIndex((id) => upIndex.has(id));\n if (meet < 0) return null;\n const backward = up.slice(0, upIndex.get(down[meet]!)).map((id) => step(id, \"backward\"));\n const forward = down.slice(0, meet).reverse().map((id) => step(id, \"forward\"));\n return [...backward, ...forward];\n}\n\n/** Every snapshot from the lineage root down to `toId`, so an id from any ancestor resolves. */\nexport function rootPath(lineage: Lineage, toId: number, maxHops = DEFAULT_MAX_HOPS): LineageStep[] {\n return ancestry(lineage, toId, maxHops).reverse().map((id) => step(id, \"forward\"));\n}\n\nfunction step(snapshotId: number, direction: LineageStep[\"direction\"]): LineageStep {\n return { snapshotId, direction };\n}\n","import type { IdAlias, IdAliasReason } from \"../types.js\";\nimport { lineagePath, rootPath, type Lineage, type LineageStep } from \"./lineage.js\";\n\nexport type AliasLoader = (snapshotId: number) => readonly IdAlias[];\n\nexport interface AliasResolution {\n requestedId: string;\n /** The id in the target snapshot's id space; equal to `requestedId` when nothing moved. */\n id: string;\n /** Each alias applied in walk order; a backward step lists the alias it undid. */\n hops: IdAlias[];\n /** `move` when any hop changed directory, otherwise the last hop's reason; absent without hops. */\n reason?: IdAliasReason;\n}\n\nexport interface AliasChain {\n fromSnapshotId: number | null;\n toSnapshotId: number;\n /** False when the snapshots share no alias base; only the target's own aliases apply then, as before 0.15.0. */\n connected: boolean;\n steps: readonly LineageStep[];\n resolve(id: string): string;\n trace(id: string): AliasResolution;\n}\n\nexport interface AliasChainInput {\n lineage: Lineage;\n loadAliases: AliasLoader;\n /** Null resolves an id from any ancestor of `to`. */\n from: number | null;\n to: number;\n maxHops?: number;\n}\n\ninterface StepMap {\n direction: LineageStep[\"direction\"];\n byId: ReadonlyMap<string, IdAlias>;\n}\n\n// Sorted so an inverted merge (two old ids, one new) always undoes to the same old id.\nfunction stepMap(aliases: readonly IdAlias[], direction: StepMap[\"direction\"]): StepMap {\n const byId = new Map<string, IdAlias>();\n const sorted = [...aliases].sort((a, b) => compare(a.oldId, b.oldId) || compare(a.newId, b.newId));\n for (const alias of sorted) {\n const key = direction === \"forward\" ? alias.oldId : alias.newId;\n if (!byId.has(key)) byId.set(key, alias);\n }\n return { direction, byId };\n}\n\nfunction compare(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\nfunction overallReason(hops: readonly IdAlias[]): IdAliasReason | undefined {\n if (hops.length === 0) return undefined;\n return hops.some((h) => h.reason === \"move\") ? \"move\" : hops[hops.length - 1]!.reason;\n}\n\n// One lookup per snapshot: a snapshot's aliases are one git diff, so A to B plus B to A is a swap, not a cycle.\nfunction walk(requestedId: string, maps: readonly StepMap[]): AliasResolution {\n let id = requestedId;\n const hops: IdAlias[] = [];\n for (const { direction, byId } of maps) {\n const alias = byId.get(id);\n if (!alias) continue;\n hops.push(alias);\n id = direction === \"forward\" ? alias.newId : alias.oldId;\n }\n return { requestedId, id, hops, reason: overallReason(hops) };\n}\n\nfunction chainSteps(input: AliasChainInput): { steps: LineageStep[]; connected: boolean } {\n if (input.from === null) return { steps: rootPath(input.lineage, input.to, input.maxHops), connected: true };\n const path = lineagePath(input.lineage, input.from, input.to, input.maxHops);\n if (path) return { steps: path, connected: true };\n return { steps: [{ snapshotId: input.to, direction: \"forward\" }], connected: false };\n}\n\n/** Carry node ids from one snapshot into another across every rename between them. */\nexport function createAliasChain(input: AliasChainInput): AliasChain {\n const { steps, connected } = chainSteps(input);\n const maps = steps.map((s) => stepMap(input.loadAliases(s.snapshotId), s.direction));\n const cache = new Map<string, AliasResolution>();\n const trace = (id: string): AliasResolution => {\n let hit = cache.get(id);\n if (!hit) cache.set(id, (hit = walk(id, maps)));\n return hit;\n };\n return { fromSnapshotId: input.from, toSnapshotId: input.to, connected, steps, resolve: (id) => trace(id).id, trace };\n}\n","import { detectGitHead, isGitAncestor, resolveGitRef } from \"../git-renames.js\";\nimport { rowToSnapshot, type SnapshotDbRow } from \"../rows.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { SnapshotRow } from \"../types.js\";\nimport { createAliasChain, type AliasChain, type AliasResolution } from \"./alias-chain.js\";\nimport { buildLineage, type Lineage } from \"./lineage.js\";\n\nexport interface AliasChainOptions {\n maxHops?: number;\n}\n\nexport interface ResolveAliasOptions extends AliasChainOptions {\n /** The snapshot the id was read in; omitted, the id may come from any ancestor of the target. */\n fromSnapshotId?: number;\n}\n\nexport interface PriorSnapshotOptions {\n /** Only snapshots older than this id count; omitted, every snapshot does. */\n before?: number;\n /** A git checkout to resolve `ref` in; without it only the snapshot's `ref` label matches. */\n repoRoot?: string;\n}\n\n// The store's listSnapshots caps at a limit; lineage needs every snapshot.\nfunction allSnapshots(store: CodeGraphStore): SnapshotRow[] {\n return (store.db.prepare(\"SELECT * FROM snapshot ORDER BY id\").all() as SnapshotDbRow[]).map(rowToSnapshot);\n}\n\n/** The alias-base tree over every snapshot in the store. */\nexport function loadLineage(store: CodeGraphStore): Lineage {\n return buildLineage(allSnapshots(store));\n}\n\n/** Carry node ids from `fromSnapshotId` into `toSnapshotId` through every alias between them, in either direction. */\nexport function aliasChain(\n store: CodeGraphStore,\n fromSnapshotId: number | null,\n toSnapshotId: number,\n options: AliasChainOptions = {},\n): AliasChain {\n return createAliasChain({\n lineage: loadLineage(store),\n loadAliases: (id) => store.listAliases(id),\n from: fromSnapshotId,\n to: toSnapshotId,\n maxHops: options.maxHops,\n });\n}\n\n/** Resolve an id to its form in `toSnapshotId`: `a.ts` renamed to `b.ts` then `c.ts` resolves to `c.ts`. */\nexport function resolveAlias(\n store: CodeGraphStore,\n id: string,\n toSnapshotId: number,\n options: ResolveAliasOptions = {},\n): AliasResolution {\n return aliasChain(store, options.fromSnapshotId ?? null, toSnapshotId, options).trace(id);\n}\n\n/**\n * The newest snapshot a ref denotes: first the snapshot of the commit git resolves\n * `ref` to (with `repoRoot`), else the newest snapshot whose `ref` label is `ref`.\n */\nexport function priorSnapshotForRef(\n store: CodeGraphStore,\n ref: string,\n options: PriorSnapshotOptions = {},\n): SnapshotRow | null {\n const before = options.before ?? Number.POSITIVE_INFINITY;\n const candidates = allSnapshots(store).filter((s) => s.id < before).reverse();\n const commit = options.repoRoot ? resolveGitRef(options.repoRoot, `${ref}^{commit}`) : null;\n const byCommit = commit ? candidates.find((s) => s.commitHash === commit) : undefined;\n return byCommit ?? candidates.find((s) => s.ref === ref) ?? null;\n}\n\n/** The commit a new snapshot is indexed at (default HEAD), in the checkout that can verify its history. */\nexport interface AliasTarget {\n repoRoot: string;\n commit?: string;\n}\n\n/** The commit an index of `target` records, or null outside a git checkout. */\nexport function aliasTargetCommit(target: AliasTarget): string | null {\n return target.commit ?? detectGitHead(target.repoRoot);\n}\n\n/**\n * The snapshot a new index of `ref` computes its aliases against: its own ref's newest\n * committed snapshot, else any, and only when that commit is an ancestor of `target`.\n */\nexport function aliasBaseFor(store: CodeGraphStore, ref: string, target: AliasTarget): SnapshotRow | null {\n const committed = allSnapshots(store).filter((s) => s.commitHash).reverse();\n const candidate = committed.find((s) => s.ref === ref) ?? committed[0];\n if (!candidate?.commitHash) return null;\n // A force-pushed ref can leave the candidate on an unrelated history, where a rename diff is noise.\n const commit = aliasTargetCommit(target);\n return commit && isGitAncestor(target.repoRoot, candidate.commitHash, commit) ? candidate : null;\n}\n","import { buildAliases, detectRenames } from \"../git-renames.js\";\nimport { SYMBOL_ID_SEP } from \"../extractors/ids.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { GraphNode, IdAlias } from \"../types.js\";\nimport { aliasBaseFor, aliasTargetCommit } from \"./store-identity.js\";\n\nexport interface AliasBridgeInput {\n rootDir: string;\n idRoot: string;\n ref: string;\n commitHash?: string;\n detectRenames?: boolean;\n nodes: ReadonlyMap<string, GraphNode>;\n}\n\n/** The snapshot a new snapshot's aliases start from, and the aliases themselves. */\nexport interface AliasBridge {\n baseSnapshotId: number | null;\n aliases: IdAlias[];\n}\n\n// `#` sorts directly before `$`, so this range is exactly the ids of one file's symbols.\nconst SYMBOLS_OF_FILE = `SELECT id FROM node\n WHERE snapshot_id = ? AND id >= ? AND id < ? AND kind = 'symbol'`;\n\nfunction symbolIdsOf(store: CodeGraphStore, snapshotId: number, fileId: string): string[] {\n const rows = store.db.prepare(SYMBOLS_OF_FILE).all(snapshotId, `${fileId}#`, `${fileId}$`) as { id: string }[];\n return rows.map((r) => r.id);\n}\n\n/**\n * Symbol aliases derived from file aliases, so `a.ts#Job.run` follows `a.ts` to\n * `b.ts#Job.run`. Only symbols present on both sides get one; a symbol renamed\n * inside the moved file is not followed.\n */\nexport function movedSymbolAliases(\n store: CodeGraphStore,\n baseSnapshotId: number,\n fileAliases: readonly IdAlias[],\n nodes: ReadonlyMap<string, GraphNode>,\n): IdAlias[] {\n const out: IdAlias[] = [];\n for (const alias of fileAliases) {\n if (nodes.get(alias.newId)?.kind !== \"file\") continue;\n for (const oldId of symbolIdsOf(store, baseSnapshotId, alias.oldId)) {\n const newId = alias.newId + SYMBOL_ID_SEP + oldId.slice(alias.oldId.length + 1);\n if (nodes.get(newId)?.kind === \"symbol\") out.push({ oldId, newId, reason: alias.reason });\n }\n }\n return out;\n}\n\nfunction renameAliases(input: AliasBridgeInput, baseCommit: string, target: string): IdAlias[] {\n if (input.detectRenames === false || target === baseCommit) return [];\n const pairs = detectRenames({ repoRoot: input.rootDir, fromCommit: baseCommit, toCommit: target });\n return buildAliases(input.idRoot, pairs);\n}\n\n/** File, module, and symbol aliases bridging a rename between the alias base's commit and this index. */\nexport function computeAliasBridge(store: CodeGraphStore, input: AliasBridgeInput): AliasBridge {\n const target = { repoRoot: input.rootDir, commit: input.commitHash };\n const base = aliasBaseFor(store, input.ref, target);\n const commit = base ? aliasTargetCommit(target) : null;\n if (!base?.commitHash || !commit) return { baseSnapshotId: null, aliases: [] };\n const fileAliases = renameAliases(input, base.commitHash, commit);\n const symbols = movedSymbolAliases(store, base.id, fileAliases, input.nodes);\n return { baseSnapshotId: base.id, aliases: [...fileAliases, ...symbols] };\n}\n","import { readFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\n\n/**\n * Generated-code detection. Generated files (codegen output, e.g. an OpenAPI\n * `client.gen.ts`) churn and re-export in bulk, so they dominate hotspots and\n * unused-exports with noise that no human maintains. This module supplies one\n * reusable predicate — {@link isGeneratedFile} — used to mark such files so the\n * hotspot / unused-export surfaces can exclude them at their shared boundary.\n *\n * Detection has two tiers: the authoritative `.gitattributes linguist-generated`\n * markers a repo already declares, and a filename/path heuristic fallback for\n * repos that declare nothing.\n */\n\n// Fallback heuristic: `*.gen.*` / `*.generated.*` basenames and any path with a\n// `generated/` segment. Anchored to a segment boundary so `regenerated/` and a\n// stray `foogen.ts` don't match.\nconst HEURISTIC_FILE_RE = /(?:^|\\/)[^/]*\\.(?:gen|generated)\\.[^/]*$/;\nconst HEURISTIC_DIR_RE = /(?:^|\\/)generated\\//;\n\n/** True when a path looks generated by filename/dir convention alone. */\nexport function isGeneratedByHeuristic(id: string): boolean {\n return HEURISTIC_FILE_RE.test(id) || HEURISTIC_DIR_RE.test(id);\n}\n\n/**\n * A file is generated when it matches a repo-declared `linguist-generated`\n * pattern or the filename/path heuristic. `patterns` come from\n * {@link parseGeneratedPatterns}; pass `[]` when no `.gitattributes` exists.\n */\nexport function isGeneratedFile(\n id: string,\n patterns: readonly RegExp[],\n): boolean {\n for (const rx of patterns) if (rx.test(id)) return true;\n return isGeneratedByHeuristic(id);\n}\n\n/** Read `<rootDir>/.gitattributes` and compile its linguist-generated patterns. */\nexport function loadGeneratedPatterns(rootDir: string): RegExp[] {\n try {\n const content = readFileSync(path.join(rootDir, \".gitattributes\"), \"utf-8\");\n return parseGeneratedPatterns(content);\n } catch {\n return [];\n }\n}\n\n/**\n * Parse `.gitattributes` text into regexes for every path pattern marked\n * `linguist-generated` (bare, or `=true`). A later `-linguist-generated` /\n * `=false` on the same line wins (git's last-attribute-wins rule), letting a\n * repo opt a path back out.\n */\nexport function parseGeneratedPatterns(content: string): RegExp[] {\n const out: RegExp[] = [];\n for (const raw of content.split(\"\\n\")) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const parsed = /^(\"(?:[^\"\\\\]|\\\\.)*\"|\\S+)\\s*(.*)$/.exec(line);\n if (!parsed) continue;\n const pattern = unquote(parsed[1]!);\n if (generatedAttr(parsed[2]!.split(/\\s+/).filter(Boolean)) === true) {\n out.push(gitattributesPatternToRegex(pattern));\n }\n }\n return out;\n}\n\n/** Resolve the effective linguist-generated value from a line's attribute tokens. */\nfunction generatedAttr(attrs: readonly string[]): boolean | undefined {\n let value: boolean | undefined;\n for (const a of attrs) {\n if (a === \"linguist-generated\" || a === \"linguist-generated=true\") value = true;\n else if (a === \"-linguist-generated\" || a === \"linguist-generated=false\") value = false;\n }\n return value;\n}\n\nfunction unquote(token: string): string {\n return token.startsWith('\"') && token.endsWith('\"')\n ? token.slice(1, -1).replace(/\\\\(.)/g, \"$1\")\n : token;\n}\n\n/**\n * Convert a gitignore-style `.gitattributes` path pattern to a regex matched\n * against a repo-relative posix id: a slash-free pattern matches at any depth\n * (`*.gen.ts`), a pattern with a slash anchors to the root, `**` crosses dirs,\n * `*`/`?` stay within a segment, and a trailing `/` matches a directory prefix.\n */\nexport function gitattributesPatternToRegex(pattern: string): RegExp {\n let p = pattern;\n const isDir = p.endsWith(\"/\");\n if (isDir) p = p.slice(0, -1);\n let body = \"\";\n for (let i = 0; i < p.length; i++) {\n const c = p[i]!;\n if (c === \"*\" && p[i + 1] === \"*\") {\n body += \".*\";\n i++;\n } else if (c === \"*\") body += \"[^/]*\";\n else if (c === \"?\") body += \"[^/]\";\n else body += c.replace(/[.+(){}|^$\\\\[\\]]/, \"\\\\$&\");\n }\n const prefix = p.includes(\"/\") ? \"^\" : \"(?:^|/)\";\n return new RegExp(prefix + body + (isDir ? \"(?:/|$)\" : \"$\"));\n}\n","import type { GraphNode, NodeRole } from \"./types.js\";\nimport { isGeneratedFile, loadGeneratedPatterns } from \"./generated.js\";\n\nconst TEST_RE = /(?:^|\\/)(?:__tests__\\/|tests?\\/)|\\.(?:test|spec)(?:\\.[a-z]+)?$/;\nconst FIXTURE_RE = /(?:^|\\/)fixtures(?:\\/|$)/;\n// One-off tooling under scripts/ or dormant archive/ dirs: report noise, not\n// product signal. Test-ness wins (checked first) since it's more meaningful.\nconst SCRIPT_RE = /(?:^|\\/)(?:scripts|archive)(?:\\/|$)/;\nconst BARREL_RE = /(?:^|\\/)index(?:\\.[a-z]+)?$/;\nconst TYPES_RE = /(?:^|\\/)(?:[a-z][\\w-]*\\.)?types(?:\\.[a-z]+)?$/i;\nconst CONFIG_RE = /\\.config(?:\\.[a-z]+)?$/;\n\nexport const ALL_ROLES: readonly NodeRole[] = [\n \"test\",\n \"fixture\",\n \"barrel\",\n \"types\",\n \"config\",\n \"script\",\n \"entry\",\n \"generated\",\n \"source\",\n];\n\nexport interface RoleHints {\n /** File begins with a `#!` shebang, i.e. it is an executable entry point. */\n hasShebang?: boolean;\n /** File is codegen output (`.gitattributes linguist-generated` or heuristic). */\n isGenerated?: boolean;\n}\n\nexport function classifyRole(id: string, hints?: RoleHints): NodeRole {\n // Generated wins outright: codegen output is noise for every human-facing\n // signal, so labeling it `generated` (not, say, `barrel` for a `.gen` index)\n // is what lets hotspots/unused-exports exclude it at one shared boundary.\n if (hints?.isGenerated) return \"generated\";\n if (TEST_RE.test(id)) return \"test\";\n if (FIXTURE_RE.test(id)) return \"fixture\";\n if (SCRIPT_RE.test(id)) return \"script\";\n // A shebang-prefixed file (e.g. a CLI's index.ts) is an executable entry\n // point, not re-export plumbing — check before the filename barrel heuristic\n // so it doesn't get mislabeled as `barrel`. `entry` seeds reachability (like\n // a barrel) and is exempt from the fan-out smell (an entry legitimately wires\n // up many command modules).\n if (hints?.hasShebang) return \"entry\";\n if (BARREL_RE.test(id)) return \"barrel\";\n if (TYPES_RE.test(id)) return \"types\";\n if (CONFIG_RE.test(id)) return \"config\";\n return \"source\";\n}\n\nexport interface AnnotateRolesOptions {\n /** Node ids whose source begins with a `#!` shebang. */\n shebangIds?: ReadonlySet<string>;\n /** Node ids detected as generated (codegen output). */\n generatedIds?: ReadonlySet<string>;\n}\n\ninterface ReadFileLike {\n filePath: string;\n content: string;\n}\n\n/**\n * Derive per-file role hints for a batch of read files in one pass: the shebang\n * set (executable entries) and the generated set (codegen output, detected via\n * `.gitattributes linguist-generated` under `idRoot` plus filename/path\n * heuristics). Lives here so the indexer stays at its file-size ceiling.\n */\nexport function computeRoleHints(\n readFiles: readonly ReadFileLike[],\n idRoot: string,\n toId: (root: string, filePath: string) => string,\n): AnnotateRolesOptions {\n const patterns = loadGeneratedPatterns(idRoot);\n const shebangIds = new Set<string>();\n const generatedIds = new Set<string>();\n for (const rf of readFiles) {\n const id = toId(idRoot, rf.filePath);\n if (rf.content.startsWith(\"#!\")) shebangIds.add(id);\n if (isGeneratedFile(id, patterns)) generatedIds.add(id);\n }\n return { shebangIds, generatedIds };\n}\n\nexport function annotateRoles(\n nodes: readonly GraphNode[],\n options?: AnnotateRolesOptions,\n): GraphNode[] {\n return nodes.map((n) =>\n n.kind === \"file\" || n.kind === \"module\"\n ? {\n ...n,\n role:\n n.role ??\n classifyRole(n.id, {\n hasShebang: options?.shebangIds?.has(n.id) ?? false,\n isGenerated: options?.generatedIds?.has(n.id) ?? false,\n }),\n }\n : n,\n );\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { isExcludedDir, shouldIncludeFile } from \"@titan-design/code-parser\";\n\n/**\n * Recursively collect the source files under `rootDirs` that pass the ingest\n * filter for `languages`, deduped by absolute path across roots (walk order\n * preserved). Extracted from the indexer (C-61): as a function nested inside the\n * per-root loop, the recursive walker carried a cognitive-complexity nesting\n * bonus that made it the indexer's single most complex function (cx 19, above\n * the exported entry point). Hoisting it here — one recursion helper, one\n * directory branch — drops it well under budget and makes the walker unit-\n * testable in isolation.\n */\nexport async function walkSourceFiles(\n rootDirs: readonly string[],\n languages: readonly string[],\n): Promise<string[]> {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const rootDir of rootDirs) {\n await collectFiles(rootDir, rootDir, languages, seen, out);\n }\n return out;\n}\n\nasync function collectFiles(\n dir: string,\n rootDir: string,\n languages: readonly string[],\n seen: Set<string>,\n out: string[],\n): Promise<void> {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n // Prune excluded directories (node_modules, dist, .git, …) instead of\n // recursing into them: `shouldIncludeFile` already rejects every file\n // beneath them, so descending only pays to `readdir` a potentially multi-GB\n // tree and discard all of it. Pruning here changes no output but makes\n // `graph index` on a repo with installed dependencies orders of magnitude\n // faster (found dogfooding on a pnpm monorepo — a whole-repo index hung in\n // node_modules for minutes).\n if (entry.isDirectory()) {\n if (isExcludedDir(entry.name)) continue;\n await collectFiles(full, rootDir, languages, seen, out);\n } else if (entry.isFile() && !seen.has(full)) {\n const relative = path.relative(rootDir, full);\n if (shouldIncludeFile(relative, [...languages])) {\n seen.add(full);\n out.push(full);\n }\n }\n }\n}\n","import type { GraphEdge, GraphNode } from \"./types.js\";\n\n/** Edge weight (C-51 reference count), floored at 1 for unweighted edges. */\nexport function edgeWeight(e: GraphEdge): number {\n const w = (e.attrs as { weight?: number } | undefined)?.weight;\n return typeof w === \"number\" && w > 0 ? w : 1;\n}\n\n/**\n * Drop `references` edges (C-53) whose target `symbol` node doesn't exist — an\n * aliased re-export chain, or a barrel that changed under a reused file, can\n * resolve a name to an origin that doesn't declare it. `calls` edges (TP-323)\n * are dropped the same way, which is how a callee name that maps to no symbol\n * node is discarded rather than guessed. Only these two can dangle\n * (imports/re-exports resolve to always-emitted file/external nodes). Mutates\n * `edges` in place.\n */\nexport function pruneDanglingReferences(\n nodes: ReadonlyMap<string, GraphNode>,\n edges: Map<string, GraphEdge>,\n): void {\n for (const [key, edge] of edges) {\n const symbolLayer = edge.kind === \"references\" || edge.kind === \"calls\";\n if (symbolLayer && (!nodes.has(edge.dstId) || !nodes.has(edge.srcId))) edges.delete(key);\n }\n}\n\n/**\n * Resolve edges that land on a barrel (`role=\"barrel\"` — a bare `index.*`\n * re-export file) onto the files the barrel actually re-exports from, so\n * downstream signals measure the real dependency surface instead of the\n * re-export plumbing. A cross-package `import … from \"@codewatch/graph\"`\n * resolves to the barrel; without this every such import piles onto the barrel\n * as an artificial hub while the module that truly does the work is\n * under-credited.\n *\n * An inbound edge `F → B` (weight w) is split across B's outbound re-export\n * targets `t_i` in proportion to each target's re-export weight `r_i` (C-51:\n * the count of names B forwards from `t_i`). This CONSERVES w — no magnitude\n * inflation, unlike a uniform fan-out that turns one import into N edges — and\n * attributes it by how much of the barrel each target supplies. Resolution\n * recurses through barrel chains (a barrel re-exporting a barrel) with a\n * visited guard against re-export cycles; a barrel with no resolvable\n * re-exports is left as its own target so the dependency is never dropped.\n *\n * Pure over the assembled node/edge set, so it is deterministic regardless of\n * how much of an incremental index was reused.\n */\nexport function resolveBarrelEdges(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n): GraphEdge[] {\n const barrels = new Set<string>();\n for (const n of nodes) if (n.role === \"barrel\") barrels.add(n.id);\n if (barrels.size === 0) return [...edges];\n\n // Each barrel's outbound forwarding edges (re-exports, and any import it then\n // re-exports), keyed by barrel id, as {target, weight} to split inbound by.\n // A `references` edge is per-symbol *usage*, not re-export plumbing (a pure\n // barrel emits none — it only `export … from`s), so it's excluded from the\n // forwarding basis and kept as a real edge below (C-68).\n const forwards = new Map<string, { dst: string; weight: number }[]>();\n for (const e of edges) {\n if (!barrels.has(e.srcId) || e.kind === \"references\") continue;\n const arr = forwards.get(e.srcId) ?? [];\n arr.push({ dst: e.dstId, weight: edgeWeight(e) });\n forwards.set(e.srcId, arr);\n }\n\n const cache = new Map<string, Map<string, number>>();\n /** Distribution of a target over real (non-barrel) files: realId → fraction (sums to 1). */\n function resolve(id: string, seen: ReadonlySet<string>): Map<string, number> {\n if (!barrels.has(id)) return new Map([[id, 1]]);\n const cached = cache.get(id);\n if (cached) return cached;\n const targets = forwards.get(id);\n const total = targets?.reduce((s, t) => s + t.weight, 0) ?? 0;\n // Dead-end barrel (forwards nothing resolvable) or a cycle: keep as itself.\n if (!targets || total === 0 || seen.has(id)) return new Map([[id, 1]]);\n const out = new Map<string, number>();\n const nextSeen = new Set(seen).add(id);\n for (const t of targets) {\n const share = t.weight / total;\n for (const [real, frac] of resolve(t.dst, nextSeen)) {\n out.set(real, (out.get(real) ?? 0) + share * frac);\n }\n }\n cache.set(id, out);\n return out;\n }\n\n const resolved: GraphEdge[] = [];\n for (const e of edges) {\n // A barrel's own outbound import/re-export edges are plumbing — captured by\n // resolving its inbound edges to targets — so drop them to avoid\n // double-crediting. A `references` edge is genuine usage (e.g. a composition\n // root that the role classifier labels `barrel` but which actually consumes\n // a symbol via `const { runX } = await import(...)`, C-68), so keep it.\n if (barrels.has(e.srcId) && e.kind !== \"references\") continue;\n if (!barrels.has(e.dstId)) {\n resolved.push(e);\n continue;\n }\n const w = edgeWeight(e);\n for (const [real, frac] of resolve(e.dstId, new Set())) {\n if (real === e.srcId) continue; // a barrel that circles back to the importer\n resolved.push({\n ...e,\n dstId: real,\n attrs: { ...(e.attrs as object), weight: w * frac },\n });\n }\n }\n return resolved;\n}\n","import { createHash } from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport type { Node } from \"web-tree-sitter\";\nimport { getLanguageFromPath, type ParsedFile } from \"@titan-design/code-parser\";\nimport type { CodeGraphStore } from \"./store.js\";\nimport { fileId, parseSymbolId } from \"./extractors/ids.js\";\nimport { SOURCE_METRIC_NAMES } from \"./source-metrics.js\";\nimport { DEAD_CODE_METRIC_NAMES } from \"./analysis/dead-code.js\";\nimport { GROWTH_RISK_METRIC_NAMES } from \"./analysis/growth-risk.js\";\nimport { reconstructCosmetic, reconstructFragment } from \"./reconstruct.js\";\nimport type { Extractor } from \"@titan-design/code-parser\";\nimport type {\n FileFingerprint,\n GraphEdge,\n GraphFragment,\n GraphMetric,\n GraphNode,\n} from \"./types.js\";\n\n/** SHA-256 of file content. The fingerprint that gates per-file reuse. */\nexport function hashContent(content: string): string {\n return createHash(\"sha256\").update(content, \"utf8\").digest(\"hex\");\n}\n\n/**\n * Comment/whitespace-insensitive hash of a file's parse structure (C-18). Walks\n * the tree-sitter tree emitting each node's type plus leaf text, skipping comment\n * nodes; whitespace and positions are absent from the tree, so a pure reformat or\n * comment edit yields the SAME signature while any token change yields a new one.\n * Two files with an equal signature therefore produce identical edges and AST\n * metrics and differ only in line spans (and loc) — the COSMETIC reuse class.\n */\nexport function structuralSignature(file: ParsedFile): string {\n const parts: string[] = [];\n const visit = (node: Node): void => {\n if (node.type === \"comment\") return;\n parts.push(node.type);\n if (node.childCount === 0) parts.push(node.text);\n for (const child of node.children) if (child) visit(child);\n };\n visit(file.tree.rootNode);\n return hashContent(parts.join(\"\u001f\"));\n}\n\n/** The languages that have an extractor; anything else is skipped by the walk. */\nexport type SourceLanguage = \"typescript\" | \"python\";\n\nexport interface ReadFile {\n filePath: string;\n language: SourceLanguage;\n content: string;\n hash: string;\n}\n\nfunction sourceLanguage(filePath: string): SourceLanguage | null {\n const language = getLanguageFromPath(filePath);\n return language === \"typescript\" || language === \"python\" ? language : null;\n}\n\n/** Read + hash every source file. Cheap I/O; the parse/extract it gates is not. */\nexport async function readSourceFiles(\n filePaths: readonly string[],\n): Promise<ReadFile[]> {\n const out: ReadFile[] = [];\n for (const filePath of filePaths) {\n const language = sourceLanguage(filePath);\n if (language === null) continue;\n const content = await fs.readFile(filePath, \"utf-8\");\n out.push({ filePath, language, content, hash: hashContent(content) });\n }\n return out;\n}\n\n/**\n * Split files into those to (re)parse and those reusable from the prior snapshot.\n * A file is reused when its content hash matches AND it is not in `affected` — the\n * set (C-20) whose edges a file-membership delta changed, which must re-extract\n * despite being byte-identical. `affected` is empty when membership is unchanged.\n */\nexport function classifyForReuse(\n readFiles: readonly ReadFile[],\n idRoot: string,\n reuse: ReuseBasis | null,\n affected: ReadonlySet<string> = new Set(),\n): { toParse: ReadFile[]; reusedFileIds: string[] } {\n const toParse: ReadFile[] = [];\n const reusedFileIds: string[] = [];\n for (const rf of readFiles) {\n const id = fileId(idRoot, rf.filePath);\n if (reuse && reuse.fingerprints.get(id) === rf.hash && !affected.has(id)) {\n reusedFileIds.push(id);\n } else {\n toParse.push(rf);\n }\n }\n return { toParse, reusedFileIds };\n}\n\n/** COSMETIC/structural split of the freshly-parsed files, plus every parsed and\n * reused file's structural signature (to persist for the next run). */\nexport interface ParsedClassification {\n /** Parsed files whose structure matches the basis — reuse edges, skip extract. */\n cosmeticFileIds: Set<string>;\n /** fileId → structural signature, for every parsed file and every reused file. */\n structuralByFileId: Map<string, string>;\n}\n\n/**\n * Split freshly-parsed files into COSMETIC (structure unchanged vs the basis —\n * only comments/whitespace moved) and STRUCTURAL (a real token change), by\n * comparing each file's structural signature against the basis (C-18). Also\n * carries reused (NONE-tier) files' signatures forward so they survive across\n * generations rather than decaying to NULL after their first reuse.\n */\nexport function classifyParsed(\n parsedByPath: Map<string, ParsedFile>,\n idRoot: string,\n reuse: ReuseBasis | null,\n reusedFileIds: readonly string[],\n affected: ReadonlySet<string> = new Set(),\n): ParsedClassification {\n const cosmeticFileIds = new Set<string>();\n const structuralByFileId = new Map<string, string>();\n for (const [filePath, parsed] of parsedByPath) {\n const id = fileId(idRoot, filePath);\n const sig = structuralSignature(parsed);\n structuralByFileId.set(id, sig);\n // A file affected by a membership delta (C-20) has a stale basis edge set even\n // though its structure is unchanged, so it must NOT take the cosmetic path.\n if (reuse && !affected.has(id) && reuse.structuralHashes.get(id) === sig) {\n cosmeticFileIds.add(id);\n }\n }\n if (reuse) {\n for (const id of reusedFileIds) {\n const sig = reuse.structuralHashes.get(id);\n if (sig !== undefined) structuralByFileId.set(id, sig);\n }\n }\n return { cosmeticFileIds, structuralByFileId };\n}\n\n/**\n * Build fragments for all files in walk order — extracting STRUCTURAL freshly-\n * parsed files, reconstructing NONE-tier reused ones, and (C-18) reconstructing\n * COSMETIC files from the basis edges while refreshing their symbol line spans\n * from the fresh parse, skipping the expensive ts-morph extract. Walk order is\n * preserved so the merge dedup resolves shared nodes identically to a full index.\n */\nexport function assembleFragments(input: {\n readFiles: readonly ReadFile[];\n idRoot: string;\n parsedByPath: Map<string, ParsedFile>;\n reuse: ReuseBasis | null;\n cosmeticFileIds: ReadonlySet<string>;\n extractor: Extractor<GraphFragment>;\n}): GraphFragment[] {\n const fragments: GraphFragment[] = [];\n for (const rf of input.readFiles) {\n const parsed = input.parsedByPath.get(rf.filePath);\n const id = fileId(input.idRoot, rf.filePath);\n if (parsed && input.reuse && input.cosmeticFileIds.has(id)) {\n fragments.push(\n reconstructCosmetic(input.idRoot, rf.filePath, id, input.reuse, parsed),\n );\n } else if (parsed) {\n fragments.push(...input.extractor.extract(parsed));\n } else if (input.reuse) {\n fragments.push(\n reconstructFragment(input.idRoot, rf.filePath, id, input.reuse),\n );\n }\n }\n return fragments;\n}\n\n/**\n * One fingerprint per file (content hash + C-18 structural signature), to persist\n * for the next run to diff against. The structural signature is looked up per\n * file; a file with none (e.g. a non-TS file, or a reuse carried from a pre-C-18\n * basis) stores NULL and simply can't take the cosmetic path next time.\n */\nexport function buildFingerprints(\n readFiles: readonly ReadFile[],\n idRoot: string,\n structuralByFileId: ReadonlyMap<string, string>,\n): FileFingerprint[] {\n return readFiles.map((rf) => {\n const id = fileId(idRoot, rf.filePath);\n return {\n fileId: id,\n contentHash: rf.hash,\n structuralHash: structuralByFileId.get(id),\n };\n });\n}\n\n/**\n * Everything from a prior snapshot needed to rebuild an unchanged file's\n * contribution to the graph without re-parsing it: its content fingerprint,\n * the node table (to look up external-node names), outbound edges grouped by\n * source file (a symbol's `calls` edges under the file declaring it), and the source-content metrics (loc, complexity, lcom4, ...).\n */\nexport interface ReuseBasis {\n snapshotId: number;\n fingerprints: Map<string, string>;\n /** Per-file structural signature (C-18); empty for a pre-C-18 basis. */\n structuralHashes: Map<string, string>;\n nodesById: Map<string, GraphNode>;\n edgesBySrc: Map<string, GraphEdge[]>;\n sourceMetricsByFile: Map<string, GraphMetric[]>;\n /** Symbol nodes grouped by their declaring file id, to carry forward for reused files (C-53). */\n symbolsByFile: Map<string, GraphNode[]>;\n}\n\n/**\n * Pick the most recent snapshot usable as a reuse basis: same index version and\n * carrying file fingerprints. Older snapshots predate the fingerprint table and\n * can't be diffed, so we return null and the caller does a full index.\n */\nexport function loadReuseBasis(\n db: CodeGraphStore,\n indexVersion: string,\n): ReuseBasis | null {\n for (const snap of db.listSnapshots({ limit: 50 })) {\n if (snap.indexVersion !== indexVersion) continue;\n const fingerprints = db.listFingerprints(snap.id);\n if (fingerprints.length === 0) continue;\n\n const nodesById = new Map<string, GraphNode>();\n const symbolsByFile = new Map<string, GraphNode[]>();\n // Opt into the symbol layer: reuse must carry symbol nodes and their inbound\n // reference edges forward for unchanged files (C-53).\n for (const n of db.listNodes(snap.id, { includeSymbols: true })) {\n nodesById.set(n.id, n);\n if (n.kind === \"symbol\" && n.parentId) {\n const bucket = symbolsByFile.get(n.parentId);\n if (bucket) bucket.push(n);\n else symbolsByFile.set(n.parentId, [n]);\n }\n }\n\n const edgesBySrc = new Map<string, GraphEdge[]>();\n for (const e of db.listEdges(snap.id, { includeReferences: true })) {\n // A `calls` edge leaves a symbol (TP-323); file it under the declaring file so reuse carries it.\n const fileKey = parseSymbolId(e.srcId)?.fileId ?? e.srcId;\n const bucket = edgesBySrc.get(fileKey);\n if (bucket) bucket.push(e);\n else edgesBySrc.set(fileKey, [e]);\n }\n\n const sourceMetricsByFile = new Map<string, GraphMetric[]>();\n for (const m of db.listMetrics(snap.id)) {\n // Source-content, dead-code, and growth-risk metrics are pure functions of\n // a file's bytes, so they carry forward verbatim for an unchanged file.\n if (\n !SOURCE_METRIC_NAMES.has(m.name) &&\n !DEAD_CODE_METRIC_NAMES.has(m.name) &&\n !GROWTH_RISK_METRIC_NAMES.has(m.name)\n )\n continue;\n // Per-symbol metrics (C-58) live on `<fileId>#<name>` nodes; bucket them\n // under their parent file so an unchanged file carries its symbol\n // complexity forward alongside its file-level source metrics.\n const node = nodesById.get(m.nodeId);\n const fileKey =\n node?.kind === \"symbol\" && node.parentId ? node.parentId : m.nodeId;\n const bucket = sourceMetricsByFile.get(fileKey);\n if (bucket) bucket.push(m);\n else sourceMetricsByFile.set(fileKey, [m]);\n }\n\n const structuralHashes = new Map<string, string>();\n for (const f of fingerprints) {\n if (f.structuralHash) structuralHashes.set(f.fileId, f.structuralHash);\n }\n\n return {\n snapshotId: snap.id,\n fingerprints: new Map(fingerprints.map((f) => [f.fileId, f.contentHash])),\n structuralHashes,\n nodesById,\n edgesBySrc,\n sourceMetricsByFile,\n symbolsByFile,\n };\n }\n return null;\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/**\n * Comment, docstring and code line counts for one function (TP-322). Lines are\n * counted as distinct source rows, so two comments on one row count once. The\n * docstring is documentation, not narration: it counts toward neither comment\n * nor body lines.\n */\nexport interface CommentLineStats {\n commentLines: number;\n docstringLines: number;\n bodyLines: number;\n commentRatio: number;\n}\n\n/** `fn` is the function node, `body` its body, `lines` the file's content split on newlines. */\nexport function commentLineStats(fn: Node, body: Node, lines: readonly string[]): CommentLineStats {\n const docstring = pythonDocstring(body);\n const comments = functionComments(fn, body);\n const commentLines = rowsOf(comments).size;\n const bodyLines = codeRows(body, docstring, comments, lines);\n return {\n commentLines,\n docstringLines: docstring ? rowSpan(docstring) : jsDocLines(fn),\n bodyLines,\n commentRatio: commentLines / Math.max(bodyLines, 1),\n };\n}\n\n/** The leading string statement of a Python block, which Python binds to `__doc__`. */\nexport function pythonDocstring(body: Node): Node | null {\n if (body.type !== \"block\") return null;\n const first = body.namedChildren.find((c) => c !== null && c.type !== \"comment\");\n if (first?.type !== \"expression_statement\" || first.namedChildCount !== 1) return null;\n return first.namedChildren[0]?.type === \"string\" ? first : null;\n}\n\n/** Statements of the body, docstring and comments aside; an expression-bodied arrow is its own statement. */\nexport function bodyStatements(body: Node, docstring: Node | null = pythonDocstring(body)): Node[] {\n if (body.type !== \"block\" && body.type !== \"statement_block\") return [body];\n return body.namedChildren.filter(\n (c): c is Node => c !== null && c.type !== \"comment\" && c.id !== docstring?.id,\n );\n}\n\n/** Python parses a block's leading comment as the block's sibling, so its comments are taken from the whole def after the signature. */\nexport function functionComments(fn: Node, body: Node): Node[] {\n if (body.type !== \"block\") return descendantsOfType(body, \"comment\");\n const signatureEnd = fn.childForFieldName(\"parameters\")?.endIndex ?? body.startIndex;\n return descendantsOfType(fn, \"comment\").filter((c) => c.startIndex >= signatureEnd);\n}\n\nexport function descendantsOfType(root: Node, type: string): Node[] {\n const out: Node[] = [];\n const visit = (node: Node): void => {\n if (node.type === type) out.push(node);\n for (const child of node.namedChildren) if (child) visit(child);\n };\n visit(root);\n return out;\n}\n\nfunction rowSpan(node: Node): number {\n return node.endPosition.row - node.startPosition.row + 1;\n}\n\nfunction rowsOf(nodes: readonly Node[]): Set<number> {\n const rows = new Set<number>();\n for (const n of nodes) {\n for (let r = n.startPosition.row; r <= n.endPosition.row; r++) rows.add(r);\n }\n return rows;\n}\n\n/** Rows under the body's statements that still hold code once comments are blanked out. */\nfunction codeRows(body: Node, docstring: Node | null, comments: readonly Node[], lines: readonly string[]): number {\n let count = 0;\n for (const row of rowsOf(bodyStatements(body, docstring))) {\n if (codeOnRow(row, lines[row] ?? \"\", comments).trim() !== \"\") count++;\n }\n return count;\n}\n\nfunction codeOnRow(row: number, text: string, comments: readonly Node[]): string {\n let out = text;\n for (const c of comments) {\n if (row < c.startPosition.row || row > c.endPosition.row) continue;\n const from = row === c.startPosition.row ? c.startPosition.column : 0;\n const to = row === c.endPosition.row ? c.endPosition.column : out.length;\n out = out.slice(0, from) + \" \".repeat(Math.max(to - from, 0)) + out.slice(to);\n }\n return out;\n}\n\n/** A `/** … *\\/` block ending on the row above the declaration, or on its first row. */\nfunction jsDocLines(fn: Node): number {\n const anchor = declarationAnchor(fn);\n const prev = anchor.previousNamedSibling;\n if (prev?.type !== \"comment\" || !prev.text.startsWith(\"/**\")) return 0;\n const gap = anchor.startPosition.row - prev.endPosition.row;\n return gap === 0 || gap === 1 ? rowSpan(prev) : 0;\n}\n\n/** The node a JSDoc block sits beside: the `const` or `export` wrapping a function, not the function itself. */\nfunction declarationAnchor(fn: Node): Node {\n let anchor = fn;\n if (fn.parent?.type === \"variable_declarator\") anchor = fn.parent.parent ?? fn;\n while (anchor.parent?.type === \"export_statement\") anchor = anchor.parent;\n return anchor;\n}\n","import type { Node } from \"web-tree-sitter\";\nimport { functionComments } from \"./comment-lines.js\";\n\n/**\n * Narrating comments (TP-322): a comment inside a function body that restates\n * the statement right after it, such as `// increment the retry count` above\n * `retryCount += 1`. A candidate signal, not a verdict: the match is a plain\n * token overlap, deterministic and cheap.\n */\n\nconst MIN_SHARED = 2;\nconst MIN_SHARE_OF_COMMENT = 0.5;\n\nconst STOPWORDS = new Set([\n \"the\", \"and\", \"for\", \"this\", \"that\", \"with\", \"from\", \"into\", \"then\", \"else\", \"when\", \"not\",\n \"are\", \"was\", \"has\", \"have\", \"its\", \"our\", \"all\", \"any\", \"can\", \"will\", \"just\", \"now\",\n \"return\", \"const\", \"let\", \"var\", \"def\", \"self\", \"none\", \"true\", \"false\", \"null\", \"undefined\",\n \"new\", \"await\", \"async\", \"function\",\n]);\n\nconst IDENTIFIER_TYPES = new Set([\n \"identifier\",\n \"property_identifier\",\n \"shorthand_property_identifier\",\n \"type_identifier\",\n]);\n\nexport function countNarratingComments(fn: Node, body: Node): number {\n let count = 0;\n for (const comment of functionComments(fn, body)) {\n const target = trailedStatement(comment) ?? nextStatement(comment);\n if (target && narrates(comment.text, target)) count++;\n }\n return count;\n}\n\n/** A comment on the same row as the end of the statement before it describes that statement. */\nfunction trailedStatement(comment: Node): Node | null {\n const prev = comment.previousNamedSibling;\n if (!prev || prev.type === \"comment\") return null;\n return prev.endPosition.row === comment.startPosition.row ? prev : null;\n}\n\n/** Lowercased word tokens of length 3 or more, split on non-word characters, underscores and camelCase humps. */\nexport function identifierTokens(text: string): Set<string> {\n const words = text.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\").split(/[^A-Za-z0-9]+/);\n const out = new Set<string>();\n for (const w of words) {\n const t = w.toLowerCase();\n if (t.length >= 3 && !STOPWORDS.has(t)) out.add(t);\n }\n return out;\n}\n\n/** A run of comment rows describes the first statement below it, inside the block a Python comment sits beside. */\nfunction nextStatement(comment: Node): Node | null {\n let next = comment.nextNamedSibling;\n while (next?.type === \"comment\") next = next.nextNamedSibling;\n if (next?.type !== \"block\") return next;\n return next.namedChildren.find((c) => c !== null && c.type !== \"comment\") ?? null;\n}\n\nfunction narrates(commentText: string, statement: Node): boolean {\n const said = identifierTokens(commentText);\n if (said.size === 0) return false;\n const code = identifierTokens(statementIdentifiers(statement).join(\" \"));\n let shared = 0;\n for (const t of said) if (code.has(t)) shared++;\n return shared >= MIN_SHARED || shared / said.size >= MIN_SHARE_OF_COMMENT;\n}\n\nfunction statementIdentifiers(statement: Node): string[] {\n const out: string[] = [];\n const visit = (node: Node): void => {\n if (IDENTIFIER_TYPES.has(node.type)) out.push(node.text);\n for (const child of node.namedChildren) if (child) visit(child);\n };\n visit(statement);\n return out;\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { GraphMetric } from \"../types.js\";\nimport { bodyStatements, descendantsOfType } from \"./comment-lines.js\";\nimport { identifierTokens } from \"./narrating-comments.js\";\n\n/**\n * Exception-handling metrics (TP-322), pure functions of one file's bytes. A\n * handler is swallowed when all it does is nothing, skip, bail out empty, or\n * log: the error stops here and no caller learns of it. Written on every file,\n * zeros included, so percentiles over a snapshot see the clean files too.\n */\nexport const EXCEPTION_METRIC_NAMES: readonly string[] = [\"except_count\", \"except_density\", \"swallowed_except\"];\n\nconst HANDLER_TYPES = [\"except_clause\", \"except_group_clause\", \"catch_clause\"];\nconst SILENT_STATEMENTS = new Set([\"pass_statement\", \"continue_statement\", \"empty_statement\"]);\nconst EMPTY_VALUES = new Set([\"None\", \"null\", \"undefined\"]);\nconst LOGGING_TOKENS = new Set([\"log\", \"logger\", \"logging\", \"warn\", \"warning\", \"warnings\", \"print\", \"console\"]);\nconst EXCEPT_CLAUSE_TYPES = new Set([\"except_clause\", \"except_group_clause\"]);\nconst OPTIONAL_IMPORT_EXCEPT_TYPES = new Set([\"ImportError\", \"ModuleNotFoundError\"]);\n\nexport function exceptionMetrics(nodeId: string, root: Node, loc: number): GraphMetric[] {\n const handlers = HANDLER_TYPES.flatMap((type) => descendantsOfType(root, type));\n const swallowed = handlers.filter((h) => isSwallowed(h)).length;\n return [\n { nodeId, name: \"except_count\", value: handlers.length, unit: \"count\" },\n { nodeId, name: \"except_density\", value: loc === 0 ? 0 : (handlers.length * 100) / loc, unit: \"per100loc\" },\n { nodeId, name: \"swallowed_except\", value: swallowed, unit: \"count\" },\n ];\n}\n\nfunction isSwallowed(handler: Node): boolean {\n if (isOptionalImportExcept(handler)) return false;\n const body = handler.childForFieldName(\"body\") ?? handler.namedChildren.find((c) => c?.type === \"block\");\n if (!body) return false;\n const statements = bodyStatements(body, null);\n if (statements.length === 0) return true;\n return statements.length === 1 && isSilent(statements[0]!);\n}\n\n/**\n * True for `except ImportError`, `except ModuleNotFoundError`, or a tuple of only\n * those two (with an optional `as name`) — the standard optional-dependency idiom,\n * never counted as swallowed regardless of what the body does.\n */\nfunction isOptionalImportExcept(handler: Node): boolean {\n if (!EXCEPT_CLAUSE_TYPES.has(handler.type)) return false;\n const value = handler.childForFieldName(\"value\");\n if (!value) return false;\n const typeExpr = value.type === \"as_pattern\" ? value.namedChild(0) : value;\n if (!typeExpr) return false;\n if (typeExpr.type === \"identifier\") return OPTIONAL_IMPORT_EXCEPT_TYPES.has(typeExpr.text);\n if (typeExpr.type !== \"tuple\") return false;\n const names = typeExpr.namedChildren.filter((c): c is Node => c !== null);\n return names.length > 0 && names.every((n) => n.type === \"identifier\" && OPTIONAL_IMPORT_EXCEPT_TYPES.has(n.text));\n}\n\nfunction isSilent(statement: Node): boolean {\n if (SILENT_STATEMENTS.has(statement.type)) return true;\n const value = statement.namedChildren[0];\n if (statement.type === \"return_statement\") return !value || EMPTY_VALUES.has(value.text);\n if (statement.type !== \"expression_statement\" || !value) return false;\n if (value.type === \"ellipsis\") return true;\n return isLoggingCall(value);\n}\n\nfunction isLoggingCall(node: Node): boolean {\n if (node.type !== \"call\" && node.type !== \"call_expression\") return false;\n const callee = node.childForFieldName(\"function\");\n if (!callee) return false;\n for (const token of identifierTokens(callee.text)) if (LOGGING_TOKENS.has(token)) return true;\n return false;\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/**\n * Cognitive complexity per Sonarsource (\"Cognitive Complexity: A new way of\n * measuring understandability\"). Compared to cyclomatic, this:\n *\n * - Doesn't grow per `case` in a switch — the switch counts once.\n * - Adds a nesting bonus: nested control structures cost more than flat ones.\n * - Treats `else if` chains as one increment each, not as nested ifs.\n *\n * Returns the score for a function body. Caller drives the per-function loop.\n */\nexport function cognitiveComplexityOf(body: Node, language: string): number {\n const handler = language === \"python\" ? PY_HANDLER : TS_HANDLER;\n return scoreNode(body, 0, handler);\n}\n\ninterface LanguageHandler {\n /** Returns the nesting-charged increment (+1 + nesting), or 0 if the node\n * isn't a complexity contributor. */\n structuralIncrement: (node: Node, nesting: number) => number;\n /** True if this node increases nesting depth for its descendants. */\n isNesting: (node: Node) => boolean;\n /** Flat +1 increments (no nesting bonus): logical operators, `else`, etc. */\n flatIncrement: (node: Node) => number;\n}\n\nconst TS_STRUCTURAL = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_statement\",\n \"catch_clause\",\n \"ternary_expression\",\n]);\n\nconst PY_STRUCTURAL = new Set([\n \"if_statement\",\n \"for_statement\",\n \"while_statement\",\n \"except_clause\",\n \"conditional_expression\",\n // elif_clause is intentionally NOT here — it's a flat continuation of an\n // existing if (counted in flatIncrement). Including it would charge both\n // a structural and a flat +1.\n]);\n\nconst TS_NESTING = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_statement\",\n \"catch_clause\",\n \"function_declaration\",\n \"method_definition\",\n \"arrow_function\",\n]);\n\nconst PY_NESTING = new Set([\n \"if_statement\",\n \"for_statement\",\n \"while_statement\",\n \"except_clause\",\n \"function_definition\",\n \"lambda\",\n]);\n\nconst TS_HANDLER: LanguageHandler = {\n structuralIncrement(node, nesting) {\n return TS_STRUCTURAL.has(node.type) ? 1 + nesting : 0;\n },\n isNesting(node) {\n return TS_NESTING.has(node.type);\n },\n flatIncrement(node) {\n if (node.type === \"else_clause\") return 1;\n if (\n node.type === \"binary_expression\" &&\n isLogicalOp(node) &&\n !isInnerOfSameOpChain(node, \"binary_expression\")\n ) {\n return 1;\n }\n return 0;\n },\n};\n\nconst PY_HANDLER: LanguageHandler = {\n structuralIncrement(node, nesting) {\n return PY_STRUCTURAL.has(node.type) ? 1 + nesting : 0;\n },\n isNesting(node) {\n return PY_NESTING.has(node.type);\n },\n flatIncrement(node) {\n if (node.type === \"elif_clause\" || node.type === \"else_clause\") return 1;\n if (\n node.type === \"boolean_operator\" &&\n !isInnerOfSameOpChain(node, \"boolean_operator\")\n ) {\n return 1;\n }\n return 0;\n },\n};\n\nfunction isLogicalOp(node: Node): boolean {\n const op = node.childForFieldName(\"operator\");\n return !!op && (op.text === \"&&\" || op.text === \"||\");\n}\n\n/**\n * Per Sonarsource: a sequence of like binary logical operators counts once,\n * not per occurrence. `a && b && c` is one chain (+1), not two (+2). Skip\n * the increment when this node's operator matches its parent's operator —\n * the outer node already counted the chain.\n */\nfunction isInnerOfSameOpChain(node: Node, parentType: string): boolean {\n const parent = node.parent;\n if (!parent || parent.type !== parentType) return false;\n const op = node.childForFieldName(\"operator\")?.text;\n const parentOp = parent.childForFieldName(\"operator\")?.text;\n return !!op && op === parentOp;\n}\n\n/**\n * A nested if under an else_clause is part of an `else if` chain — the\n * else_clause already counted +1, and treating it as a nested if would\n * double-charge AND inflate the nesting bonus. Skip both.\n */\nfunction isElseIf(node: Node): boolean {\n if (node.type !== \"if_statement\" && node.type !== \"elif_clause\") return false;\n const parent = node.parent;\n return !!parent && parent.type === \"else_clause\";\n}\n\nfunction scoreNode(\n node: Node,\n nesting: number,\n handler: LanguageHandler,\n): number {\n const elseIf = isElseIf(node);\n const structural = elseIf ? 0 : handler.structuralIncrement(node, nesting);\n const flat = handler.flatIncrement(node);\n const childNesting =\n !elseIf && handler.isNesting(node) ? nesting + 1 : nesting;\n\n let score = structural + flat;\n for (const child of node.namedChildren) {\n if (child) score += scoreNode(child, childNesting, handler);\n }\n return score;\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport type { GraphMetric } from \"./types.js\";\n\n/**\n * Lack of Cohesion of Methods, LCOM4 variant: count connected components\n * in the graph where each method is a node and two methods are linked when\n * they share at least one `this.<x>` (or `self.<x>`) reference or one calls\n * the other. LCOM4=1 → cohesive class; LCOM4>1 → the class could be split.\n *\n * Static methods and constructors are excluded (they don't bind to `this`).\n * Files with no classes emit no metrics. Files with classes emit\n * `lcom4_max` (max LCOM4 across classes in the file) and `class_count`.\n */\nexport function computeLcomMetrics(\n file: ParsedFile,\n fileId: string,\n): GraphMetric[] {\n const classes = collectClasses(file);\n if (classes.length === 0) return [];\n const out: GraphMetric[] = [\n {\n nodeId: fileId,\n name: \"class_count\",\n value: classes.length,\n unit: \"count\",\n },\n ];\n const scores = classes\n .map((c) => lcom4OfClass(c, file.language))\n .filter((s): s is number => s !== null);\n if (scores.length > 0) {\n out.push({\n nodeId: fileId,\n name: \"lcom4_max\",\n value: Math.max(...scores),\n unit: \"count\",\n });\n }\n return out;\n}\n\nfunction collectClasses(file: ParsedFile): Node[] {\n const isClass =\n file.language === \"python\"\n ? (n: Node) => n.type === \"class_definition\"\n : (n: Node) =>\n n.type === \"class_declaration\" || n.type === \"class_expression\";\n const out: Node[] = [];\n const visit = (node: Node): void => {\n if (isClass(node)) out.push(node);\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(file.tree.rootNode);\n return out;\n}\n\ninterface MethodInfo {\n name: string;\n usedNames: Set<string>;\n}\n\nfunction lcom4OfClass(classNode: Node, language: string): number | null {\n const methods = collectMethods(classNode, language);\n if (methods.length === 0) return null;\n if (methods.length === 1) return 1;\n return countComponents(methods);\n}\n\nfunction collectMethods(classNode: Node, language: string): MethodInfo[] {\n return language === \"python\"\n ? collectPythonMethods(classNode)\n : collectTsMethods(classNode);\n}\n\nfunction collectTsMethods(classNode: Node): MethodInfo[] {\n const body = classNode.childForFieldName(\"body\");\n if (!body) return [];\n const out: MethodInfo[] = [];\n for (const child of body.namedChildren) {\n if (!child || child.type !== \"method_definition\") continue;\n if (hasStaticModifier(child)) continue;\n const name = methodName(child);\n if (!name || name === \"constructor\") continue;\n out.push({ name, usedNames: thisRefs(child, \"this\") });\n }\n return out;\n}\n\nfunction collectPythonMethods(classNode: Node): MethodInfo[] {\n const body = classNode.childForFieldName(\"body\");\n if (!body) return [];\n const out: MethodInfo[] = [];\n for (const child of body.namedChildren) {\n if (!child || child.type !== \"function_definition\") continue;\n const name = child.childForFieldName(\"name\")?.text;\n if (!name || name === \"__init__\") continue;\n if (isPythonStaticOrClassMethod(child)) continue;\n out.push({ name, usedNames: thisRefs(child, \"self\") });\n }\n return out;\n}\n\nfunction methodName(methodNode: Node): string | null {\n const nameNode = methodNode.childForFieldName(\"name\");\n return nameNode?.text ?? null;\n}\n\nfunction hasStaticModifier(methodNode: Node): boolean {\n for (const child of methodNode.children) {\n if (child?.type === \"static\") return true;\n }\n return false;\n}\n\nfunction isPythonStaticOrClassMethod(funcNode: Node): boolean {\n let prev = funcNode.previousNamedSibling;\n while (prev && prev.type === \"decorator\") {\n const text = prev.text;\n if (text.includes(\"@staticmethod\") || text.includes(\"@classmethod\")) {\n return true;\n }\n prev = prev.previousNamedSibling;\n }\n return false;\n}\n\nfunction thisRefs(methodNode: Node, selfKeyword: string): Set<string> {\n const out = new Set<string>();\n const visit = (n: Node): void => {\n collectThisRef(n, selfKeyword, out);\n for (const child of n.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(methodNode);\n return out;\n}\n\nfunction collectThisRef(\n n: Node,\n selfKeyword: string,\n out: Set<string>,\n): void {\n if (n.type === \"member_expression\" || n.type === \"attribute\") {\n const obj = n.childForFieldName(\"object\");\n if (!obj) return;\n if (matchesSelf(obj, selfKeyword)) {\n const prop =\n n.childForFieldName(\"property\") ?? n.childForFieldName(\"attribute\");\n if (prop) out.add(prop.text);\n }\n }\n}\n\nfunction matchesSelf(node: Node, selfKeyword: string): boolean {\n if (selfKeyword === \"this\") return node.type === \"this\";\n return node.type === \"identifier\" && node.text === selfKeyword;\n}\n\nfunction countComponents(methods: readonly MethodInfo[]): number {\n const n = methods.length;\n const parent = Array.from({ length: n }, (_, i) => i);\n const find = (i: number): number => {\n while (parent[i]! !== i) {\n parent[i] = parent[parent[i]!]!;\n i = parent[i]!;\n }\n return i;\n };\n const union = (a: number, b: number): void => {\n const ra = find(a);\n const rb = find(b);\n if (ra !== rb) parent[ra] = rb;\n };\n for (let i = 0; i < n; i++) {\n for (let j = i + 1; j < n; j++) {\n if (areLinked(methods[i]!, methods[j]!)) union(i, j);\n }\n }\n const roots = new Set<number>();\n for (let i = 0; i < n; i++) roots.add(find(i));\n return roots.size;\n}\n\nfunction areLinked(a: MethodInfo, b: MethodInfo): boolean {\n if (a.usedNames.has(b.name)) return true;\n if (b.usedNames.has(a.name)) return true;\n for (const name of a.usedNames) {\n if (b.usedNames.has(name)) return true;\n }\n return false;\n}\n","import type { Node } from \"web-tree-sitter\";\nimport { bodyStatements } from \"./comment-lines.js\";\n\n/**\n * Pass-through functions (TP-322): the body is one call that forwards every\n * parameter, in order, as a bare argument, as in `def load(path): return read(path)`.\n * Only the exact case is claimed; a keyword argument, a reordering, a dropped or\n * transformed parameter, or a function with no parameters at all is not a pass-through.\n */\n\nconst RECEIVERS = new Set([\"self\", \"cls\"]);\nconst CALL_TYPES = new Set([\"call\", \"call_expression\"]);\nconst WRAPPER_TYPES = new Set([\"return_statement\", \"expression_statement\"]);\nconst PY_NAMED_PARAMS = new Set([\"default_parameter\", \"typed_default_parameter\"]);\nconst PY_SEPARATORS = new Set([\"keyword_separator\", \"positional_separator\"]);\n\nexport function isPassThrough(fn: Node, body: Node): boolean {\n const call = soleCall(body);\n if (!call) return false;\n const params = parameterShapes(fn);\n if (!params || params.length === 0) return false;\n const args = argumentShapes(call);\n return args !== null && args.length === params.length && args.every((a, i) => a === params[i]);\n}\n\nfunction soleCall(body: Node): Node | null {\n const statements = bodyStatements(body);\n if (statements.length !== 1) return null;\n const only = statements[0]!;\n if (CALL_TYPES.has(only.type)) return only;\n if (!WRAPPER_TYPES.has(only.type) || only.namedChildCount !== 1) return null;\n const value = only.namedChildren[0]!;\n return CALL_TYPES.has(value.type) ? value : null;\n}\n\n/** Each parameter as the argument text that forwards it (`a`, `*args`, `...rest`), or null when one cannot be forwarded bare. */\nfunction parameterShapes(fn: Node): string[] | null {\n const bare = fn.childForFieldName(\"parameter\");\n if (bare) return [bare.text];\n const list = fn.childForFieldName(\"parameters\");\n if (!list) return null;\n const shapes: string[] = [];\n for (const p of list.namedChildren) {\n if (!p || p.type === \"comment\" || PY_SEPARATORS.has(p.type)) continue;\n const shape = parameterShape(p);\n if (shape === null) return null;\n shapes.push(shape);\n }\n return RECEIVERS.has(shapes[0] ?? \"\") ? shapes.slice(1) : shapes;\n}\n\nfunction parameterShape(p: Node): string | null {\n if (p.type === \"identifier\") return p.text;\n if (p.type === \"list_splat_pattern\" || p.type === \"dictionary_splat_pattern\") return p.text;\n if (PY_NAMED_PARAMS.has(p.type)) return p.childForFieldName(\"name\")?.text ?? null;\n if (p.type === \"typed_parameter\") return parameterShape(p.namedChildren[0]!);\n if (p.type === \"required_parameter\" || p.type === \"optional_parameter\") {\n const pattern = p.childForFieldName(\"pattern\");\n return pattern ? tsPatternShape(pattern) : null;\n }\n return tsPatternShape(p);\n}\n\nfunction tsPatternShape(pattern: Node): string | null {\n if (pattern.type === \"identifier\") return pattern.text;\n if (pattern.type === \"rest_pattern\") return `...${pattern.namedChildren[0]?.text ?? \"\"}`;\n if (pattern.type === \"assignment_pattern\") {\n const left = pattern.childForFieldName(\"left\");\n return left ? tsPatternShape(left) : null;\n }\n return null;\n}\n\nfunction argumentShapes(call: Node): string[] | null {\n const list = call.childForFieldName(\"arguments\");\n if (!list || (list.type !== \"argument_list\" && list.type !== \"arguments\")) return null;\n const shapes: string[] = [];\n for (const a of list.namedChildren) {\n if (!a || a.type === \"comment\") continue;\n const shape = argumentShape(a);\n if (shape === null) return null;\n shapes.push(shape);\n }\n return shapes;\n}\n\nfunction argumentShape(a: Node): string | null {\n if (a.type === \"identifier\") return a.text;\n const inner = a.namedChildren[0];\n if (inner?.type !== \"identifier\") return null;\n if (a.type === \"list_splat\") return `*${inner.text}`;\n if (a.type === \"dictionary_splat\") return `**${inner.text}`;\n if (a.type === \"spread_element\") return `...${inner.text}`;\n return null;\n}\n","import type { Node } from \"web-tree-sitter\";\nimport { commentLineStats, type CommentLineStats } from \"./analysis/comment-lines.js\";\nimport { countNarratingComments } from \"./analysis/narrating-comments.js\";\nimport { isPassThrough } from \"./analysis/pass-through.js\";\nimport { symbolId } from \"./extractors/ids.js\";\nimport type { GraphMetric } from \"./types.js\";\n\n/** Comment and shape counts of one function (TP-322); `passThrough` is 1 or 0. */\nexport interface FunctionShapeStats extends CommentLineStats {\n narratingComments: number;\n passThrough: number;\n}\n\nexport interface FunctionStats extends FunctionShapeStats {\n /** Scope-qualified declared name (`Job.run`), or null for an anonymous function (e.g. `export default () => {}`). */\n name: string | null;\n cyclomatic: number;\n cognitive: number;\n nestingDepth: number;\n /** Lines spanned by the whole function node, signature included. */\n loc: number;\n}\n\ntype NumericStat = \"cyclomatic\" | \"cognitive\" | \"nestingDepth\" | \"loc\" | keyof FunctionShapeStats;\n\n/** Per-symbol metric name and the unit and function stat it reports. */\nconst SYMBOL_METRICS: readonly { name: string; stat: NumericStat; unit: string }[] = [\n { name: \"symbol_cognitive\", stat: \"cognitive\", unit: \"count\" },\n { name: \"symbol_cyclomatic\", stat: \"cyclomatic\", unit: \"count\" },\n { name: \"symbol_loc\", stat: \"loc\", unit: \"lines\" },\n { name: \"symbol_max_nesting\", stat: \"nestingDepth\", unit: \"count\" },\n { name: \"symbol_comment_lines\", stat: \"commentLines\", unit: \"lines\" },\n { name: \"symbol_docstring_lines\", stat: \"docstringLines\", unit: \"lines\" },\n { name: \"symbol_body_lines\", stat: \"bodyLines\", unit: \"lines\" },\n { name: \"symbol_comment_ratio\", stat: \"commentRatio\", unit: \"ratio\" },\n { name: \"symbol_narrating_comments\", stat: \"narratingComments\", unit: \"count\" },\n { name: \"symbol_pass_through\", stat: \"passThrough\", unit: \"count\" },\n];\n\nexport const SYMBOL_METRIC_NAMES: readonly string[] = SYMBOL_METRICS.map((m) => m.name);\n\n/**\n * Per-symbol metrics (C-58, C-64, TP-317): for each named function whose qualified\n * name has a `symbol` node on this file, emit every SYMBOL_METRICS entry on that\n * node (`<fileId>#<qualifiedName>`). Model B (C-64) gives non-exported helpers a\n * node too, so internal functions get their own values here, not just exports. A\n * qualified name shared by several functions (a getter/setter pair) takes the max\n * of each stat independently; a declared name with no function (a bare class) emits nothing.\n */\nexport function symbolMetrics(\n fileId: string,\n stats: readonly FunctionStats[],\n symbolNames: ReadonlySet<string>,\n): GraphMetric[] {\n if (symbolNames.size === 0) return [];\n const byName = new Map<string, Record<NumericStat, number>>();\n for (const s of stats) {\n if (!s.name || !symbolNames.has(s.name)) continue;\n const prev = byName.get(s.name);\n if (!prev) {\n byName.set(s.name, { ...s });\n continue;\n }\n for (const { stat } of SYMBOL_METRICS) prev[stat] = Math.max(prev[stat], s[stat]);\n }\n const out: GraphMetric[] = [];\n for (const [name, values] of byName) {\n const nodeId = symbolId(fileId, name);\n for (const m of SYMBOL_METRICS) {\n out.push({ nodeId, name: m.name, value: values[m.stat], unit: m.unit });\n }\n }\n return out;\n}\n\n/** `fn` is the function node, `body` its body, `lines` the file's content split on newlines. */\nexport function functionShapeStats(fn: Node, body: Node, lines: readonly string[]): FunctionShapeStats {\n return {\n ...commentLineStats(fn, body, lines),\n narratingComments: countNarratingComments(fn, body),\n passThrough: isPassThrough(fn, body) ? 1 : 0,\n };\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport { EXCEPTION_METRIC_NAMES, exceptionMetrics } from \"./analysis/exception-handling.js\";\nimport { cognitiveComplexityOf } from \"./cognitive-complexity.js\";\nimport { computeLcomMetrics } from \"./lcom.js\";\nimport { qualify, walkScopes } from \"./scope-path.js\";\nimport { functionShapeStats, SYMBOL_METRIC_NAMES, symbolMetrics, type FunctionStats } from \"./symbol-metrics.js\";\nimport type { GraphMetric } from \"./types.js\";\n\nconst TS_FUNCTION_TYPES = new Set([\n \"function_declaration\",\n \"method_definition\",\n]);\n\nconst PY_FUNCTION_TYPES = new Set([\"function_definition\"]);\n\nconst TS_NESTING_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_statement\",\n \"try_statement\",\n]);\n\nconst PY_NESTING_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"while_statement\",\n \"try_statement\",\n]);\n\nconst TS_BRANCH_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_case\",\n \"catch_clause\",\n \"ternary_expression\",\n]);\n\nconst PY_BRANCH_TYPES = new Set([\n \"if_statement\",\n \"elif_clause\",\n \"for_statement\",\n \"while_statement\",\n \"except_clause\",\n \"conditional_expression\",\n]);\n\n/**\n * Names of every metric `computeSourceMetrics` can emit. These are pure\n * functions of a file's content, so the incremental indexer can carry them\n * forward unchanged for a byte-identical file instead of re-parsing it. If a\n * new source metric is added above, add its name here — the incremental\n * round-trip test will fail loudly if this set drifts out of sync.\n */\nexport const SOURCE_METRIC_NAMES: ReadonlySet<string> = new Set([\n \"loc\",\n \"function_count\",\n \"cyclomatic_max\",\n \"cyclomatic_sum\",\n \"cognitive_max\",\n \"cognitive_sum\",\n \"max_nesting_depth\",\n \"class_count\",\n \"lcom4_max\",\n ...EXCEPTION_METRIC_NAMES,\n // Per-symbol complexity, size, comments and shape (C-58, C-64, TP-317, TP-322), keyed\n // to `symbol` node ids. Source-local like the file-level metrics above, so an\n // unchanged file carries them forward — but their nodeId is `<fileId>#<name>`,\n // so the reuse basis buckets them under the symbol's parent file (incremental.ts).\n ...SYMBOL_METRIC_NAMES,\n]);\n\nconst EMPTY_NAMES: ReadonlySet<string> = new Set();\n\n/**\n * Per-file source metrics. `symbolNamesByFile` maps a file id to the names of\n * the `symbol` nodes it declares; when supplied, per-function complexity is\n * emitted on those symbol nodes (C-58; all declared functions since C-64). It\n * defaults to empty, so existing callers/tests that don't thread the symbol\n * layer keep emitting only file-level metrics.\n */\nexport function computeSourceMetrics(\n files: readonly ParsedFile[],\n fileIdOf: (filePath: string) => string,\n symbolNamesByFile: ReadonlyMap<string, ReadonlySet<string>> = new Map(),\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n for (const file of files) {\n const id = fileIdOf(file.filePath);\n out.push(...metricsForFile(id, file, symbolNamesByFile.get(id) ?? EMPTY_NAMES));\n }\n return out;\n}\n\nfunction metricsForFile(\n nodeId: string,\n file: ParsedFile,\n symbolNames: ReadonlySet<string>,\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n const loc = countLoc(file.content);\n out.push({ nodeId, name: \"loc\", value: loc, unit: \"lines\" });\n\n const stats = analyzeFunctions(file);\n out.push({\n nodeId,\n name: \"function_count\",\n value: stats.length,\n unit: \"count\",\n });\n\n if (stats.length > 0) {\n out.push({\n nodeId,\n name: \"cyclomatic_max\",\n value: Math.max(...stats.map((s) => s.cyclomatic)),\n unit: \"count\",\n });\n out.push({\n nodeId,\n name: \"cyclomatic_sum\",\n value: stats.reduce((acc, s) => acc + s.cyclomatic, 0),\n unit: \"count\",\n });\n out.push({\n nodeId,\n name: \"cognitive_max\",\n value: Math.max(...stats.map((s) => s.cognitive)),\n unit: \"count\",\n });\n out.push({\n nodeId,\n name: \"cognitive_sum\",\n value: stats.reduce((acc, s) => acc + s.cognitive, 0),\n unit: \"count\",\n });\n out.push({\n nodeId,\n name: \"max_nesting_depth\",\n value: Math.max(...stats.map((s) => s.nestingDepth)),\n unit: \"count\",\n });\n }\n out.push(...symbolMetrics(nodeId, stats, symbolNames));\n out.push(...computeLcomMetrics(file, nodeId));\n out.push(...exceptionMetrics(nodeId, file.tree.rootNode, loc));\n return out;\n}\n\nfunction countLoc(content: string): number {\n return content.split(\"\\n\").filter((l) => l.trim() !== \"\").length;\n}\n\nfunction analyzeFunctions(file: ParsedFile): FunctionStats[] {\n const stats: FunctionStats[] = [];\n const fnTypes =\n file.language === \"python\" ? PY_FUNCTION_TYPES : TS_FUNCTION_TYPES;\n const lines = file.content.split(\"\\n\");\n walkScopes(file.tree.rootNode, file.language === \"python\", (node, scope) => {\n const fn = functionAt(node, fnTypes);\n if (!fn) return;\n stats.push({\n name: fn.name === null ? null : qualify(scope, fn.name),\n cyclomatic: cyclomaticOf(fn.body, file.language),\n cognitive: cognitiveComplexityOf(fn.body, file.language),\n nestingDepth: nestingDepthOf(fn.body, file.language, 0),\n loc: fn.node.endPosition.row - fn.node.startPosition.row + 1,\n ...functionShapeStats(fn.node, fn.body, lines),\n });\n });\n return stats;\n}\n\n/**\n * A named, standalone function at this node, with its body and declared name —\n * or null. Covers declarations/methods (name on the node) and, crucially,\n * arrow / function-expression bound to a `const`/`let` (`export const foo =\n * () => {}`), where the name lives on the enclosing variable_declarator. Those\n * bindings were previously invisible to the analyzer (C-58) — a real complexity\n * under-count in an arrow-heavy codebase. Anonymous inline callbacks (parent is\n * a call, not a declarator) are intentionally excluded: their control flow\n * already rolls into the enclosing function's cognitive score.\n */\nfunction functionAt(\n node: Node,\n fnTypes: ReadonlySet<string>,\n): { name: string | null; body: Node; node: Node } | null {\n if (fnTypes.has(node.type)) {\n const body = node.childForFieldName(\"body\");\n return body ? { name: node.childForFieldName(\"name\")?.text ?? null, body, node } : null;\n }\n if (\n (node.type === \"arrow_function\" || node.type === \"function_expression\") &&\n node.parent?.type === \"variable_declarator\"\n ) {\n const body = node.childForFieldName(\"body\");\n if (!body) return null;\n return { name: node.parent.childForFieldName(\"name\")?.text ?? null, body, node };\n }\n return null;\n}\n\nfunction nestingDepthOf(node: Node, language: string, depth: number): number {\n const nestingTypes =\n language === \"python\" ? PY_NESTING_TYPES : TS_NESTING_TYPES;\n let maxDepth = depth;\n for (const child of node.namedChildren) {\n if (!child) continue;\n const next = nestingTypes.has(child.type) ? depth + 1 : depth;\n const childMax = nestingDepthOf(child, language, next);\n if (childMax > maxDepth) maxDepth = childMax;\n }\n return maxDepth;\n}\n\nfunction cyclomaticOf(body: Node, language: string): number {\n const branchTypes =\n language === \"python\" ? PY_BRANCH_TYPES : TS_BRANCH_TYPES;\n let complexity = 1;\n const visit = (node: Node): void => {\n if (branchTypes.has(node.type)) complexity++;\n if (node.type === \"binary_expression\") {\n const op = node.childForFieldName(\"operator\");\n if (op && (op.text === \"&&\" || op.text === \"||\")) complexity++;\n }\n if (language === \"python\" && node.type === \"boolean_operator\") {\n complexity++;\n }\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(body);\n return complexity;\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/**\n * Python counterparts of the TypeScript dead-code counts in dead-code.ts (TP-318).\n * Same three counts, same bias: claim only the decidable case and never flag\n * when unsure. Where Python's semantics differ from TypeScript's, the rule is\n * noted on the function that implements it.\n */\n\nconst TERMINALS = new Set([\n \"return_statement\",\n \"raise_statement\",\n \"break_statement\",\n \"continue_statement\",\n]);\n\n/** Nodes that open a new scope: their bindings are not the enclosing function's. */\nconst SCOPE_TYPES = new Set([\"function_definition\", \"lambda\", \"class_definition\"]);\n\n/** Parameters with a splat can't be dropped from the call shape, so they stop the trailing run. */\nconst SPLAT_TYPES = new Set([\"list_splat_pattern\", \"dictionary_splat_pattern\"]);\n\nconst RECEIVERS = new Set([\"self\", \"cls\"]);\n\nexport interface DeadCodeCounts {\n unreachable: number;\n locals: number;\n params: number;\n}\n\nexport function pythonDeadCode(root: Node): DeadCodeCounts {\n const out: DeadCodeCounts = { unreachable: 0, locals: 0, params: 0 };\n const visit = (node: Node): void => {\n if (node.type === \"block\") out.unreachable += unreachableInBlock(node);\n if (node.type === \"function_definition\") {\n const r = analyzeFunction(node);\n out.locals += r.locals;\n out.params += r.params;\n }\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(root);\n return out;\n}\n\n/** Unlike TypeScript, a `def` after a terminal is not hoisted, so it counts as unreachable too. */\nfunction unreachableInBlock(block: Node): number {\n let seenTerminal = false;\n let count = 0;\n for (const child of block.namedChildren) {\n if (!child) continue;\n if (seenTerminal && child.type !== \"comment\") count++;\n if (TERMINALS.has(child.type)) seenTerminal = true;\n }\n return count;\n}\n\n/**\n * Unused locals and trailing unused parameters of one function. A name counts\n * as used when any identifier in the function's subtree (closures included)\n * reads it. A name also bound in a nested scope is skipped, as TypeScript skips\n * shadowed names; unlike TypeScript, rebinding a name in the function's own\n * scope is one local, because Python assignment does not declare.\n */\nfunction analyzeFunction(fn: Node): { locals: number; params: number } {\n const own = ownBindings(fn);\n const nested = nestedBindings(fn);\n const refs = countReferences(fn, own.declIds);\n const isUnused = (name: string): boolean =>\n !name.startsWith(\"_\") &&\n !nested.has(name) &&\n !own.declared.has(name) &&\n (refs.get(name) ?? 0) === 0;\n\n let params = 0;\n const paramNames = ownParamNames(fn);\n for (let i = isStub(fn) ? -1 : paramNames.length - 1; i >= 0; i--) {\n const name = paramNames[i] ?? null;\n if (name !== null && isUnused(name)) params++;\n else break;\n }\n const paramSet = new Set(paramNames);\n let locals = 0;\n for (const name of own.locals) {\n if (!paramSet.has(name) && isUnused(name)) locals++;\n }\n return { locals, params };\n}\n\n/** A body of only docstrings, `...`, `pass` or `raise NotImplementedError`: an `@overload` or abstract signature, like a bodiless TypeScript overload. */\nfunction isStub(fn: Node): boolean {\n const body = fn.childForFieldName(\"body\");\n return (body?.namedChildren ?? []).every((stmt) => {\n if (!stmt || stmt.type === \"comment\" || stmt.type === \"pass_statement\") return true;\n if (stmt.type === \"raise_statement\") return /^raise NotImplementedError\\b/.test(stmt.text);\n const expr = stmt.type === \"expression_statement\" ? stmt.namedChild(0) : null;\n return expr?.type === \"ellipsis\" || expr?.type === \"string\";\n });\n}\n\n/**\n * Ordered parameter names; `null` marks a position never flagged that also stops\n * the trailing run (`*args`, `**kwargs`, `self`, `cls`). `*` and `/` separators are not parameters.\n */\nfunction ownParamNames(fn: Node): (string | null)[] {\n const params = fn.childForFieldName(\"parameters\");\n if (!params) return [];\n const out: (string | null)[] = [];\n for (const p of params.namedChildren) {\n if (!p || p.type === \"keyword_separator\" || p.type === \"positional_separator\") continue;\n const id = paramIdentifier(p);\n out.push(id && !RECEIVERS.has(id.text) ? id.text : null);\n }\n return out;\n}\n\nfunction paramIdentifier(p: Node): Node | null {\n if (p.type === \"identifier\") return p;\n if (SPLAT_TYPES.has(p.type)) return null;\n const inner = p.childForFieldName(\"name\") ?? p.namedChild(0);\n return inner?.type === \"identifier\" ? inner : null;\n}\n\n/** The plain identifier an `assignment` binds, or null for unpacking, attribute, subscript or a bare annotation. */\nfunction assignedIdentifier(node: Node): Node | null {\n if (node.type !== \"assignment\" || !node.childForFieldName(\"right\")) return null;\n const left = node.childForFieldName(\"left\");\n return left?.type === \"identifier\" ? left : null;\n}\n\ninterface OwnBindings {\n /** Plain-identifier assignment targets in the function's own scope; unpacking is always-used, as TS destructuring. */\n locals: Set<string>;\n /** Names declared `global` or `nonlocal`: they are not this function's locals. */\n declared: Set<string>;\n declIds: Set<number>;\n}\n\nfunction ownBindings(fn: Node): OwnBindings {\n const out: OwnBindings = { locals: new Set(), declared: new Set(), declIds: new Set() };\n for (const p of fn.childForFieldName(\"parameters\")?.namedChildren ?? []) {\n const id = p ? paramIdentifier(p) : null;\n if (id) out.declIds.add(id.id);\n }\n const walk = (node: Node): void => {\n if (SCOPE_TYPES.has(node.type)) return;\n const id = assignedIdentifier(node);\n if (id) {\n out.locals.add(id.text);\n out.declIds.add(id.id);\n }\n if (node.type === \"global_statement\" || node.type === \"nonlocal_statement\") {\n for (const n of node.namedChildren) if (n) out.declared.add(n.text);\n }\n for (const child of node.namedChildren) if (child) walk(child);\n };\n const body = fn.childForFieldName(\"body\");\n if (body) walk(body);\n return out;\n}\n\n/** Names bound by parameters or plain assignment inside any scope nested in the function. */\nfunction nestedBindings(fn: Node): Set<string> {\n const out = new Set<string>();\n const walk = (node: Node, nested: boolean): void => {\n const inner = nested || (node !== fn && SCOPE_TYPES.has(node.type));\n if (inner) {\n const id = assignedIdentifier(node);\n if (id) out.add(id.text);\n if (node.type === \"parameters\" || node.type === \"lambda_parameters\") {\n for (const p of node.namedChildren) {\n const pid = p ? paramIdentifier(p) : null;\n if (pid) out.add(pid.text);\n }\n }\n }\n for (const child of node.namedChildren) if (child) walk(child, inner);\n };\n walk(fn, false);\n return out;\n}\n\n/** Identifier occurrences by name across the function's subtree, minus the own binding sites. */\nfunction countReferences(fn: Node, declIds: ReadonlySet<number>): Map<string, number> {\n const out = new Map<string, number>();\n const walk = (node: Node): void => {\n if (node.type === \"identifier\" && !declIds.has(node.id)) {\n out.set(node.text, (out.get(node.text) ?? 0) + 1);\n }\n for (const child of node.namedChildren) if (child) walk(child);\n };\n const body = fn.childForFieldName(\"body\");\n if (body) walk(body);\n return out;\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport type { GraphMetric } from \"../types.js\";\nimport { pythonDeadCode, type DeadCodeCounts } from \"./dead-code-python.js\";\n\n/**\n * Function-local dead-code metrics (C-65 Phase 1). Pure functions of one file's\n * bytes — the same class as the source metrics in source-metrics.ts — so they\n * ride the content-hash incremental reuse gate. Kept in their own module (not\n * appended to source-metrics.ts) so the already-churn-hot source-metrics.ts is\n * not touched; the reuse machinery folds these names in alongside\n * SOURCE_METRIC_NAMES (see incremental.ts) and index-metrics.ts computes them\n * fresh for (re)parsed files.\n */\nexport const DEAD_CODE_METRIC_NAMES: ReadonlySet<string> = new Set([\n \"unreachable_statements\",\n \"unused_locals\",\n \"unused_params\",\n]);\n\nconst FUNCTION_TYPES = new Set([\n \"function_declaration\",\n \"function_expression\",\n \"arrow_function\",\n \"method_definition\",\n \"generator_function_declaration\",\n \"generator_function\",\n]);\n\nconst PARAM_TYPES = new Set([\"required_parameter\", \"optional_parameter\"]);\n\n/** Statements that unconditionally end control flow in their block. */\nconst TERMINALS = new Set([\n \"return_statement\",\n \"throw_statement\",\n \"break_statement\",\n \"continue_statement\",\n]);\n\n/**\n * Per-file dead-code metrics for TypeScript and Python files (Python since\n * TP-318, in dead-code-python.ts). Emitted sparsely — only when a count is > 0 —\n * so a clean file adds no rows (a full index and an incremental re-index\n * therefore produce the identical metric set). Other languages are skipped.\n */\nexport function computeDeadCodeMetrics(\n files: readonly ParsedFile[],\n fileIdOf: (filePath: string) => string,\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n for (const file of files) {\n const counts = deadCodeOf(file);\n if (!counts) continue;\n const id = fileIdOf(file.filePath);\n const { unreachable, locals, params } = counts;\n if (unreachable > 0) {\n out.push({ nodeId: id, name: \"unreachable_statements\", value: unreachable, unit: \"count\" });\n }\n if (locals > 0) {\n out.push({ nodeId: id, name: \"unused_locals\", value: locals, unit: \"count\" });\n }\n if (params > 0) {\n out.push({ nodeId: id, name: \"unused_params\", value: params, unit: \"count\" });\n }\n }\n return out;\n}\n\nfunction deadCodeOf(file: ParsedFile): DeadCodeCounts | null {\n const root = file.tree.rootNode;\n if (file.language === \"python\") return pythonDeadCode(root);\n if (file.language !== \"typescript\" && file.language !== \"tsx\") return null;\n return { unreachable: countUnreachable(root), ...countUnusedBindings(root) };\n}\n\n/**\n * Count statements that can never execute: those following an unconditional\n * terminal (`return`/`throw`/`break`/`continue`) inside the SAME\n * `statement_block`. Deliberately shallow — no CFG — so it only claims the\n * decidable case and stays near-zero false-positive:\n * - `switch` bodies are not plain blocks (fallthrough / `case` labels), so their\n * statements are never in a `statement_block` here and aren't counted.\n * - Anything after a conditional (an `if` with no guaranteed terminal) is not\n * counted, because the terminal must be a direct child of the block.\n * - A `function_declaration` after a terminal is hoisted (callable before the\n * terminal), so it is excluded; comments are ignored too.\n */\nfunction countUnreachable(root: Node): number {\n let count = 0;\n const visit = (node: Node): void => {\n if (node.type === \"statement_block\") count += unreachableInBlock(node);\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(root);\n return count;\n}\n\nfunction unreachableInBlock(block: Node): number {\n let seenTerminal = false;\n let count = 0;\n for (const child of block.namedChildren) {\n if (!child) continue;\n if (\n seenTerminal &&\n child.type !== \"comment\" &&\n child.type !== \"function_declaration\"\n ) {\n count++;\n }\n if (TERMINALS.has(child.type)) seenTerminal = true;\n }\n return count;\n}\n\n/**\n * Count unused *local variables* and *parameters* across every function in the\n * file, function-locally and conservatively (bias to NOT flag — false positives\n * are worse than misses for a health signal). Each function is analysed\n * independently; a binding is \"unused\" when its name is never referenced within\n * the function's subtree (nested closures included).\n *\n * Only PLAIN-identifier bindings are considered — destructuring/rest/pattern\n * params and locals are treated as always-used and never flagged (their\n * omit-some-keys usage is usually deliberate, and reasoning about them soundly\n * needs a scope tree). Further cuts: `_`-prefixed names (intentional-ignore) are\n * skipped; a name declared more than once anywhere in the function (shadowing) is\n * skipped rather than risk a wrong count; and an unused parameter is only counted\n * when every parameter after it is also unused (TS6133's rule — you can't drop a\n * middle parameter, only a trailing run).\n */\nfunction countUnusedBindings(root: Node): { locals: number; params: number } {\n let locals = 0;\n let params = 0;\n const visit = (node: Node): void => {\n if (FUNCTION_TYPES.has(node.type)) {\n const r = analyzeFunction(node);\n locals += r.locals;\n params += r.params;\n }\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(root);\n return { locals, params };\n}\n\nfunction analyzeFunction(fn: Node): { locals: number; params: number } {\n // All plain-id binding declarations in the subtree (own + nested): their nodes\n // are excluded from reference counts, and a name seen twice marks a shadow.\n const declIds = new Set<number>();\n const nameCount = new Map<string, number>();\n collectBindingDecls(fn, declIds, nameCount);\n\n const refs = new Map<string, number>();\n countReferences(fn, declIds, refs);\n\n const isUnused = (name: string): boolean =>\n !name.startsWith(\"_\") &&\n (nameCount.get(name) ?? 0) <= 1 &&\n (refs.get(name) ?? 0) === 0;\n\n // Params: only the trailing run of unused params counts (TS6133 middle-param rule).\n const paramNames = ownParamNames(fn);\n let params = 0;\n for (let i = paramNames.length - 1; i >= 0; i--) {\n const name = paramNames[i] ?? null;\n if (name !== null && isUnused(name)) params++;\n else break;\n }\n\n let locals = 0;\n for (const name of ownLocalNames(fn)) {\n if (isUnused(name)) locals++;\n }\n return { locals, params };\n}\n\n/**\n * Ordered parameter names of a function's `formal_parameters`. A non-plain\n * parameter (destructuring/rest) yields `null` — a position we never flag and\n * which stops the trailing-unused run (you can't drop params after it).\n * Bare single-identifier arrow params (`x => …`, no parens) are not analysed.\n */\nfunction ownParamNames(fn: Node): (string | null)[] {\n const params = fn.childForFieldName(\"parameters\");\n if (!params) return [];\n const out: (string | null)[] = [];\n for (const p of params.namedChildren) {\n if (!p || !PARAM_TYPES.has(p.type)) continue;\n const first = p.namedChild(0);\n out.push(first?.type === \"identifier\" ? first.text : null);\n }\n return out;\n}\n\n/**\n * Names of plain-identifier locals declared in the function's OWN scope — walking\n * the body but not descending into nested functions (those bindings belong to the\n * nested function). Destructuring declarators are skipped.\n */\nfunction ownLocalNames(fn: Node): string[] {\n const body = fn.childForFieldName(\"body\");\n if (!body) return [];\n const out: string[] = [];\n const walk = (node: Node): void => {\n if (FUNCTION_TYPES.has(node.type)) return;\n if (node.type === \"variable_declarator\") {\n const name = node.childForFieldName(\"name\");\n if (name?.type === \"identifier\") out.push(name.text);\n }\n for (const child of node.namedChildren) {\n if (child) walk(child);\n }\n };\n walk(body);\n return out;\n}\n\n/** Record every plain-id binding declaration node (param/local, own + nested). */\nfunction collectBindingDecls(\n fn: Node,\n ids: Set<number>,\n nameCount: Map<string, number>,\n): void {\n const mark = (n: Node | null): void => {\n if (n?.type !== \"identifier\") return;\n ids.add(n.id);\n nameCount.set(n.text, (nameCount.get(n.text) ?? 0) + 1);\n };\n const walk = (node: Node): void => {\n if (PARAM_TYPES.has(node.type)) mark(node.namedChild(0));\n else if (node.type === \"variable_declarator\") mark(node.childForFieldName(\"name\"));\n for (const child of node.namedChildren) {\n if (child) walk(child);\n }\n };\n walk(fn);\n}\n\n/** Count value references (identifier / object-shorthand) by name, minus declarations. */\nfunction countReferences(\n fn: Node,\n declIds: ReadonlySet<number>,\n out: Map<string, number>,\n): void {\n const walk = (node: Node): void => {\n if (\n (node.type === \"identifier\" ||\n node.type === \"shorthand_property_identifier\") &&\n !declIds.has(node.id)\n ) {\n out.set(node.text, (out.get(node.text) ?? 0) + 1);\n }\n for (const child of node.namedChildren) {\n if (child) walk(child);\n }\n };\n walk(fn);\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport type { GraphMetric } from \"../types.js\";\n\n/**\n * Growth-risk / scaling-smell metrics (C-66 Phase 2). Cheap, function-local\n * *heuristics* — NOT Big-O or a proven complexity class (real asymptotic\n * inference is undecidable; see the roadmap's hard NO). Pure functions of one\n * file's bytes, so they ride the content-hash incremental reuse gate, folded\n * into the carry-forward set in incremental.ts alongside the source/dead-code\n * metric names. Emitted sparsely (only when a smell is present).\n */\nexport const GROWTH_RISK_METRIC_NAMES: ReadonlySet<string> = new Set([\n \"loop_depth\",\n \"recursive_functions\",\n \"search_in_loop\",\n]);\n\nconst TS_LOOP_TYPES = new Set([\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n]);\n\nconst PY_LOOP_TYPES = new Set([\"for_statement\", \"while_statement\"]);\n\nconst NAMED_FN_TYPES = new Set([\n \"function_declaration\",\n \"generator_function_declaration\",\n \"method_definition\",\n \"function_definition\",\n]);\n\n/**\n * Array/collection methods that scan linearly — inside a loop they turn an O(n)\n * pass into an O(n·m) one (a scaling smell). `.includes`/`.indexOf` on a `Set`\n * or `Map` are O(1), so this is a heuristic, not a bound.\n */\nconst SEARCH_METHODS = new Set([\n \"includes\",\n \"indexOf\",\n \"lastIndexOf\",\n \"find\",\n \"findIndex\",\n \"some\",\n \"every\",\n \"filter\",\n]);\n\n/**\n * Per-file growth-risk metrics for TS/Python files, all SMELLS not bounds:\n * - `loop_depth` — max *lexical* loop nesting (triple-nested → 3), emitted at\n * depth ≥ 2 (depth-2 loops over two *different* collections are actually linear).\n * - `recursive_functions` — named functions that call themselves directly.\n * - `search_in_loop` — linear-scan method calls (`.includes`/`.find`/…) inside a\n * loop (an O(n) scan per iteration; `.includes` on a `Set` is O(1)).\n * All emitted sparsely (only when present). Non-TS/Python files are skipped.\n */\nexport function computeGrowthRiskMetrics(\n files: readonly ParsedFile[],\n fileIdOf: (filePath: string) => string,\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n for (const file of files) {\n const loopTypes = file.language === \"python\" ? PY_LOOP_TYPES : TS_LOOP_TYPES;\n const root = file.tree.rootNode;\n const id = fileIdOf(file.filePath);\n const depth = maxLoopDepth(root, loopTypes, 0);\n if (depth >= 2) {\n out.push({ nodeId: id, name: \"loop_depth\", value: depth, unit: \"count\" });\n }\n const recursion = countDirectRecursion(root);\n if (recursion > 0) {\n out.push({ nodeId: id, name: \"recursive_functions\", value: recursion, unit: \"count\" });\n }\n const searches = countSearchInLoop(root, loopTypes, false);\n if (searches > 0) {\n out.push({ nodeId: id, name: \"search_in_loop\", value: searches, unit: \"count\" });\n }\n }\n return out;\n}\n\n/**\n * Count named functions that call themselves directly by name — a recursion flag\n * (unbounded recursion is a scaling risk). Function-local and conservative: only\n * a plain `name(...)` call inside the same function counts; method self-calls\n * via `this.m()` and mutual recursion (which would need a call graph — a roadmap\n * hard NO) are out of scope. A name shadowed by a nested same-named function is\n * not distinguished (rare).\n */\nfunction countDirectRecursion(root: Node): number {\n let count = 0;\n const visit = (node: Node): void => {\n if (NAMED_FN_TYPES.has(node.type)) {\n const name = node.childForFieldName(\"name\")?.text;\n const body = node.childForFieldName(\"body\");\n if (name && body && callsName(body, name)) count++;\n }\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(root);\n return count;\n}\n\n/** Whether `node`'s subtree contains a direct call `name(...)`. */\nfunction callsName(node: Node, name: string): boolean {\n if (node.type === \"call_expression\") {\n const fn = node.childForFieldName(\"function\");\n if (fn?.type === \"identifier\" && fn.text === name) return true;\n }\n for (const child of node.namedChildren) {\n if (child && callsName(child, name)) return true;\n }\n return false;\n}\n\n/**\n * Count linear-scan method calls (`.includes`/`.find`/…) that occur inside a\n * loop — an O(n) search per iteration, a quadratic-shaped smell. `inLoop`\n * tracks whether the current node is lexically inside a loop body.\n */\nfunction countSearchInLoop(\n node: Node,\n loopTypes: ReadonlySet<string>,\n inLoop: boolean,\n): number {\n let count = 0;\n if (inLoop && node.type === \"call_expression\") {\n const fn = node.childForFieldName(\"function\");\n const prop = fn?.type === \"member_expression\" ? fn.childForFieldName(\"property\") : null;\n if (prop && SEARCH_METHODS.has(prop.text)) count++;\n }\n const childInLoop = inLoop || loopTypes.has(node.type);\n for (const child of node.namedChildren) {\n if (child) count += countSearchInLoop(child, loopTypes, childInLoop);\n }\n return count;\n}\n\n/** Deepest lexical nesting of loop constructs under `node`. */\nfunction maxLoopDepth(\n node: Node,\n loopTypes: ReadonlySet<string>,\n depth: number,\n): number {\n let max = depth;\n for (const child of node.namedChildren) {\n if (!child) continue;\n const next = loopTypes.has(child.type) ? depth + 1 : depth;\n const childMax = maxLoopDepth(child, loopTypes, next);\n if (childMax > max) max = childMax;\n }\n return max;\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport { buildFileModuleNodes } from \"./extractors/file-nodes.js\";\nimport { collectDeclaredSpans, type LineSpan } from \"./declared-names.js\";\nimport type { ReuseBasis } from \"./incremental.js\";\nimport type { GraphFragment, GraphNode } from \"./types.js\";\n\n/**\n * Rebuild an unchanged file's graph fragment from the prior snapshot. Produces\n * byte-for-byte the same nodes and edges the extractor would emit: file +\n * module nodes (path-derived), the symbol nodes it declares (content-derived,\n * so carried forward from the basis rather than rebuilt — C-53), the external\n * nodes its imports reference, and the outbound edges carried forward verbatim.\n */\nexport function reconstructFragment(\n repoRoot: string,\n absPath: string,\n fileId: string,\n basis: ReuseBasis,\n): GraphFragment {\n const nodes = buildFileModuleNodes(repoRoot, absPath);\n nodes.push(...(basis.symbolsByFile.get(fileId) ?? []));\n const edges = basis.edgesBySrc.get(fileId) ?? [];\n const seenExternals = new Set<string>();\n for (const edge of edges) {\n const dst = basis.nodesById.get(edge.dstId);\n if (dst?.kind === \"external\" && !seenExternals.has(dst.id)) {\n seenExternals.add(dst.id);\n nodes.push({ id: dst.id, kind: \"external\", name: dst.name });\n }\n }\n return { nodes, edges };\n}\n\n/**\n * Reconstruct a COSMETIC file's fragment (C-18): its edges + file/module/external\n * nodes are structure-invariant so they come from the basis verbatim, but its\n * symbol line spans shifted with the moved comments/whitespace, so those are\n * refreshed from the fresh parse. Produces byte-for-byte what a full extract\n * would — same names, same `exported`, same edges — with up-to-date spans, while\n * skipping the ts-morph extract entirely. Its loc + AST metrics are recomputed\n * from the same parse by the normal metrics path.\n */\nexport function reconstructCosmetic(\n repoRoot: string,\n absPath: string,\n fileId: string,\n basis: ReuseBasis,\n parsed: ParsedFile,\n): GraphFragment {\n const base = reconstructFragment(repoRoot, absPath, fileId, basis);\n const spans = collectDeclaredSpans(parsed);\n const nodes = base.nodes.map((n) =>\n n.kind === \"symbol\" ? withRefreshedSpan(n, spans) : n,\n );\n return { nodes, edges: base.edges };\n}\n\n/**\n * A symbol node with its line span refreshed from a fresh parse. Span-less\n * symbols (exported types/consts, which never carry startLine) are returned\n * unchanged; a function/method/class symbol takes the freshly-parsed span for\n * its name, matching exactly what the extractor would emit.\n */\nfunction withRefreshedSpan(\n node: GraphNode,\n spans: ReadonlyMap<string, LineSpan>,\n): GraphNode {\n const attrs = node.attrs as\n | { exported?: boolean; startLine?: number; endLine?: number }\n | undefined;\n if (!attrs || attrs.startLine === undefined) return node;\n const span = spans.get(node.name);\n if (!span) return node;\n return {\n ...node,\n attrs: { ...attrs, startLine: span.startLine, endLine: span.endLine },\n };\n}\n","import { RESOLVABLE_EXTS } from \"./extractors/module-resolution.js\";\nimport { parseSymbolId } from \"./extractors/ids.js\";\nimport type { ReuseBasis } from \"./incremental.js\";\nimport type { GraphEdge } from \"./types.js\";\n\n/**\n * Partial reuse across a file-membership delta (C-20). PR #28 fell back to a full\n * index whenever any file was added or removed, because a byte-identical file's\n * import edges resolve against the *global* file set and can change when a\n * referenced path appears or disappears. This narrows that: only files whose\n * edges are actually affected by the delta re-extract; every other unchanged\n * file is still reused.\n *\n * A stored edge carries its original `specifier`, so an unchanged file's relative\n * imports can be re-resolved over the new file-id set — no filesystem, no\n * ts-morph — to detect two effects: a target that was removed, and a target now\n * shadowed by an added file at a higher-priority resolution path.\n *\n * Known limitation (documented, sound-for-valid-code): a previously *unresolved*\n * relative import (which left no edge — a broken import in a file that didn't\n * compile) that an added file now satisfies is not detected, because there is no\n * stored specifier to re-resolve. Such a file is reused until it next changes.\n */\n\n/** Posix dirname of a repo-relative file id (`a/b/c.ts` → `a/b`). */\nfunction dirOf(id: string): string {\n const i = id.lastIndexOf(\"/\");\n return i < 0 ? \"\" : id.slice(0, i);\n}\n\n/** Normalize a posix path, collapsing `.` and `..` segments. */\nfunction normalizePosix(p: string): string {\n const out: string[] = [];\n for (const seg of p.split(\"/\")) {\n if (seg === \"\" || seg === \".\") continue;\n if (seg === \"..\") out.pop();\n else out.push(seg);\n }\n return out.join(\"/\");\n}\n\nconst JS_EXT_RE = /\\.(?:jsx?|mjs|cjs)$/;\n\n/** Candidate file ids a relative import base could resolve to, in priority order\n * — mirrors the extractor's `relativeResolutionCandidates` in id space. */\nfunction* candidateIds(base: string): Iterable<string> {\n yield base;\n for (const ext of RESOLVABLE_EXTS) yield base + ext;\n const jsExt = JS_EXT_RE.exec(base);\n if (jsExt) {\n const stem = base.slice(0, base.length - jsExt[0].length);\n for (const ext of RESOLVABLE_EXTS) yield stem + ext;\n }\n for (const ext of RESOLVABLE_EXTS) yield `${base}/index${ext}`;\n}\n\nfunction isRelative(specifier: string): boolean {\n return specifier === \".\" || specifier === \"..\" ||\n specifier.startsWith(\"./\") || specifier.startsWith(\"../\");\n}\n\n/**\n * Resolve a relative specifier from a source file id to a target file id in the\n * current file set, or null when nothing matches — the id-space equivalent of the\n * extractor's filesystem walk, so it yields the same target for the same inputs.\n */\nexport function resolveRelativeId(\n srcFileId: string,\n specifier: string,\n fileIds: ReadonlySet<string>,\n): string | null {\n const base = normalizePosix(`${dirOf(srcFileId)}/${specifier}`);\n for (const candidate of candidateIds(base)) {\n if (fileIds.has(candidate)) return candidate;\n }\n return null;\n}\n\n/** The file id an edge's target belongs to (a symbol target `f#x` → `f`). */\nfunction targetFileId(edge: GraphEdge): string {\n return parseSymbolId(edge.dstId)?.fileId ?? edge.dstId;\n}\n\n/**\n * File ids that must re-extract because the membership delta changed how their\n * imports resolve: an edge target was removed, or a relative specifier now\n * resolves to a different file (e.g. an added file shadowing the old target).\n * Empty when membership is unchanged — the caller then reuses exactly as before.\n */\nexport function computeDeltaAffected(\n basis: ReuseBasis,\n currentFileIds: ReadonlySet<string>,\n): Set<string> {\n const affected = new Set<string>();\n const removed = new Set<string>();\n for (const id of basis.fingerprints.keys()) {\n if (!currentFileIds.has(id)) removed.add(id);\n }\n const added = currentFileIds.size !== basis.fingerprints.size || removed.size > 0;\n if (!added) return affected; // membership unchanged → nothing forced\n\n for (const [srcId, edges] of basis.edgesBySrc) {\n if (!currentFileIds.has(srcId)) continue; // src itself gone\n for (const edge of edges) {\n if (isEdgeAffected(edge, srcId, removed, currentFileIds)) {\n affected.add(srcId);\n break;\n }\n }\n }\n return affected;\n}\n\nfunction isEdgeAffected(\n edge: GraphEdge,\n srcId: string,\n removed: ReadonlySet<string>,\n currentFileIds: ReadonlySet<string>,\n): boolean {\n if (removed.has(targetFileId(edge))) return true;\n const specifier = (edge.attrs as { specifier?: string } | undefined)?.specifier;\n if (!specifier || !isRelative(specifier)) return false;\n // Re-resolve the relative import; if it now lands on a different file (added\n // shadow, or the old target vanished), the file's edges must be recomputed.\n return resolveRelativeId(srcId, specifier, currentFileIds) !== targetFileId(edge);\n}\n","import type { GraphEdge, GraphMetric, GraphNode } from \"./types.js\";\nimport { edgeWeight, resolveBarrelEdges } from \"./barrel-resolve.js\";\n\ninterface DegreeCounts {\n fanIn: Map<string, number>;\n fanOut: Map<string, number>;\n}\n\n/**\n * fan_in / fan_out are file/module *structural* coupling — how many modules a\n * file depends on, and vice versa. They count only `imports`/`re-exports`\n * edges; the per-symbol `references` layer (C-53) is a finer granularity and\n * must not inflate module degree (one references edge per imported *symbol*\n * would turn \"depends on 3 modules\" into \"names 30 symbols\").\n */\nfunction isStructuralEdge(e: GraphEdge): boolean {\n return e.kind === \"imports\" || e.kind === \"re-exports\";\n}\n\nfunction countDegrees(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n): DegreeCounts {\n const fanIn = new Map<string, number>();\n const fanOut = new Map<string, number>();\n for (const n of nodes) {\n fanIn.set(n.id, 0);\n fanOut.set(n.id, 0);\n }\n for (const e of edges) {\n if (!isStructuralEdge(e)) continue;\n if (fanOut.has(e.srcId)) {\n fanOut.set(e.srcId, fanOut.get(e.srcId)! + 1);\n }\n if (fanIn.has(e.dstId)) {\n fanIn.set(e.dstId, fanIn.get(e.dstId)! + 1);\n }\n }\n return { fanIn, fanOut };\n}\n\n/**\n * Utilization: inbound edges weighted by their reference count (C-51's\n * `attrs.weight`), so it measures how heavily a file's exports are actually\n * *used*, not merely how many files name it. Computed over the\n * BARREL-RESOLVED edge set (C-53), so re-export plumbing is credited to the\n * files that do the work rather than to the `index.ts` hub everything routes\n * through. A pure barrel therefore reads utilization ~0 (fan_in still counts\n * its raw importers) — a clean re-export-hub signature. Deterministic over the\n * assembled edge set, so it stays correct under incremental reuse.\n */\nfunction weightedInbound(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n): Map<string, number> {\n const util = new Map<string, number>();\n for (const n of nodes) util.set(n.id, 0);\n for (const e of resolveBarrelEdges(nodes, edges)) {\n if (e.kind === \"calls\") continue;\n if (util.has(e.dstId)) util.set(e.dstId, util.get(e.dstId)! + edgeWeight(e));\n }\n return util;\n}\n\nexport function computeMetrics(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n): GraphMetric[] {\n const { fanIn, fanOut } = countDegrees(nodes, edges);\n const utilization = weightedInbound(nodes, edges);\n const out: GraphMetric[] = [];\n for (const n of nodes) {\n // Symbol nodes carry only utilization (how heavily the export is used).\n // fan_in/fan_out/instability are module-structural and don't apply — and\n // skipping them keeps the per-export layer from tripling the metric table.\n if (n.kind === \"symbol\") {\n out.push({ nodeId: n.id, name: \"utilization\", value: utilization.get(n.id) ?? 0, unit: \"count\" });\n continue;\n }\n const ci = fanIn.get(n.id) ?? 0;\n const co = fanOut.get(n.id) ?? 0;\n out.push({ nodeId: n.id, name: \"fan_in\", value: ci, unit: \"count\" });\n out.push({ nodeId: n.id, name: \"fan_out\", value: co, unit: \"count\" });\n out.push({ nodeId: n.id, name: \"utilization\", value: utilization.get(n.id) ?? 0, unit: \"count\" });\n if (ci + co > 0) {\n out.push({\n nodeId: n.id,\n name: \"instability\",\n value: co / (ci + co),\n unit: \"ratio\",\n });\n }\n }\n return out;\n}\n","import { readParamShape, type CallEdgeAttrs, type CallSite, type ParamShape } from \"../extractors/call-sites.js\";\nimport { parseSymbolId } from \"../extractors/ids.js\";\nimport type { GraphEdge, GraphMetric, GraphNode } from \"../types.js\";\n\nexport const CALL_METRIC_NAMES: ReadonlySet<string> = new Set([\n \"symbol_caller_count\",\n \"symbol_single_caller_helper\",\n \"symbol_constant_params\",\n]);\n\n/** Placeholder for a parameter a site does not pass; no literal's source text can equal it. */\nconst ABSENT = \"<absent>\";\n\ninterface Inbound {\n callers: Set<string>;\n sites: CallSite[];\n}\n\n/**\n * Call-graph metrics over the assembled `calls` edges (TP-323). They depend on\n * edges from every file, so they are recomputed on each index rather than\n * carried forward with a reused file. Written on each function, method and\n * class symbol (the nodes with a line span): `symbol_caller_count`, the distinct\n * other symbols or files that call it; `symbol_single_caller_helper`, 1 for a\n * non-exported, non-dunder symbol whose one caller is a symbol; and, once a callable has 2\n * resolved call sites, `symbol_constant_params`.\n */\nexport function computeCallMetrics(nodes: Iterable<GraphNode>, edges: Iterable<GraphEdge>): GraphMetric[] {\n const inbound = collectInbound(edges);\n const out: GraphMetric[] = [];\n for (const node of nodes) {\n if (node.kind !== \"symbol\" || node.attrs?.startLine === undefined) continue;\n const { callers, sites } = inbound.get(node.id) ?? { callers: new Set<string>(), sites: [] };\n out.push({ nodeId: node.id, name: \"symbol_caller_count\", value: callers.size, unit: \"count\" });\n const single = isPrivateHelper(node) && callers.size === 1 && isSymbolCaller(callers);\n out.push({ nodeId: node.id, name: \"symbol_single_caller_helper\", value: single ? 1 : 0, unit: \"count\" });\n const shape = readParamShape(node.attrs);\n if (shape && sites.length >= 2) {\n out.push({ nodeId: node.id, name: \"symbol_constant_params\", value: constantParams(shape, sites), unit: \"count\" });\n }\n }\n return out;\n}\n\n/** Callers exclude the callee itself, so recursion is not a caller; its sites still count. */\nfunction collectInbound(edges: Iterable<GraphEdge>): Map<string, Inbound> {\n const inbound = new Map<string, Inbound>();\n for (const edge of edges) {\n if (edge.kind !== \"calls\") continue;\n let entry = inbound.get(edge.dstId);\n if (!entry) inbound.set(edge.dstId, (entry = { callers: new Set(), sites: [] }));\n if (edge.srcId !== edge.dstId) entry.callers.add(edge.srcId);\n entry.sites.push(...((edge.attrs as CallEdgeAttrs | undefined)?.sites ?? []));\n }\n return inbound;\n}\n\n/** Non-exported, and not a Python `__dunder__`, which the runtime calls through its protocol. */\nfunction isPrivateHelper(node: GraphNode): boolean {\n const own = node.name.slice(node.name.lastIndexOf(\".\") + 1);\n return node.attrs?.exported === false && !(own.startsWith(\"__\") && own.endsWith(\"__\"));\n}\n\nfunction isSymbolCaller(callers: ReadonlySet<string>): boolean {\n return [...callers].every((id) => parseSymbolId(id) !== null);\n}\n\n/** Parameters every site passes the same literal, or none passes; unknown at any site means not constant. */\nexport function constantParams(shape: ParamShape, sites: readonly CallSite[]): number {\n let count = 0;\n shape.params.forEach((name, index) => {\n const values = sites.map((site) => argumentAt(site, name, index < shape.positional ? index : -1));\n if (values.every((v) => v !== null && v === values[0])) count++;\n });\n return count;\n}\n\n/** The literal text a site passes for one parameter, ABSENT when it passes nothing, or null when unknown. */\nfunction argumentAt(site: CallSite, name: string, position: number): string | null {\n if (position >= 0 && position < site.args.length) return site.args[position] ?? null;\n if (site.kwargs && Object.hasOwn(site.kwargs, name)) return site.kwargs[name] ?? null;\n if (site.kwSplat) return null;\n if (position >= 0 && site.spreadFrom !== undefined && position >= site.spreadFrom) return null;\n return ABSENT;\n}\n","import { couplingFor, type CoEditPair } from \"../history/index.js\";\nimport type { GraphMetric, GraphNode } from \"../types.js\";\n\n/** How a test↔source pairing was inferred. */\nexport type LinkMethod = \"path\" | \"coedit\";\n\nexport interface TestSourceLink {\n /** Node id of the test file. */\n testId: string;\n /** Node id of the (non-test) file it covers. */\n sourceId: string;\n method: LinkMethod;\n}\n\nexport interface LinkTestsOptions {\n /** Minimum co-edit count for a pass-2 (coedit) link. Default 2. */\n minCoEditCount?: number;\n}\n\nconst DEFAULT_MIN_CO_EDIT_COUNT = 2;\nconst TEST_INFIX_RE = /\\.(?:test|spec)(\\.[^./]+)$/;\nconst TESTS_DIR_RE = /(^|\\/)(?:__tests__|tests?)\\//;\n\n/**\n * Candidate source paths for a test file, by convention. Strips a\n * `.test`/`.spec` infix (co-located case) and collapses a `__tests__/` or\n * `test(s)/` directory segment (sub-directory case). Returns paths distinct\n * from the test id itself.\n */\nfunction pathCandidates(testId: string): string[] {\n const out = new Set<string>();\n const deInfixed = testId.replace(TEST_INFIX_RE, \"$1\");\n if (deInfixed !== testId) out.add(deInfixed);\n const deDir = deInfixed.replace(TESTS_DIR_RE, \"$1\");\n if (deDir !== testId) out.add(deDir);\n return [...out];\n}\n\nfunction splitFileIds(nodes: readonly GraphNode[]): { testIds: string[]; nonTestIds: Set<string> } {\n const testIds: string[] = [];\n const nonTestIds = new Set<string>();\n for (const n of nodes) {\n if (n.kind !== \"file\") continue;\n if (n.role === \"test\") testIds.push(n.id);\n else nonTestIds.add(n.id);\n }\n return { testIds, nonTestIds };\n}\n\n/**\n * Two-pass test↔source linker. Pass 1 pairs each test file with non-test files\n * matching its path conventions (high confidence). Pass 2 supplements tests\n * left unpaired by pass 1 with their strongest co-edited non-test partner from\n * change-coupling. Handles orphan tests (no pairing), orphan/untested sources\n * (no incoming link), and one-to-many pairings (a test matching several\n * sources, or a source covered by several tests).\n */\nexport function linkTestsToSources(\n nodes: readonly GraphNode[],\n coEditPairs: readonly CoEditPair[],\n options: LinkTestsOptions = {},\n): TestSourceLink[] {\n const minCount = options.minCoEditCount ?? DEFAULT_MIN_CO_EDIT_COUNT;\n const { testIds, nonTestIds } = splitFileIds(nodes);\n const links: TestSourceLink[] = [];\n for (const testId of testIds) {\n const matched = pathCandidates(testId).filter((c) => nonTestIds.has(c));\n if (matched.length > 0) {\n for (const sourceId of matched) {\n links.push({ testId, sourceId, method: \"path\" });\n }\n continue;\n }\n const partner = couplingFor(coEditPairs, testId).find((p) => p.count >= minCount && nonTestIds.has(p.partner));\n if (partner) {\n links.push({ testId, sourceId: partner.partner, method: \"coedit\" });\n }\n }\n return links;\n}\n\n/**\n * Per-source coverage breadth: how many distinct test files link to each\n * covered source. Emitted only for sources with at least one linked test.\n */\nexport function testCoverageCountMetrics(links: readonly TestSourceLink[]): GraphMetric[] {\n const testsBySource = groupTestsBySource(links);\n const out: GraphMetric[] = [];\n for (const [sourceId, tests] of testsBySource) {\n out.push({\n nodeId: sourceId,\n name: \"linked_test_count\",\n value: tests.size,\n unit: \"count\",\n });\n }\n return out;\n}\n\n/** Map each covered source to the set of test files that link to it. */\nexport function groupTestsBySource(links: readonly TestSourceLink[]): Map<string, Set<string>> {\n const out = new Map<string, Set<string>>();\n for (const l of links) {\n let set = out.get(l.sourceId);\n if (!set) {\n set = new Set();\n out.set(l.sourceId, set);\n }\n set.add(l.testId);\n }\n return out;\n}\n","import type { ChurnWindow } from \"./history/index.js\";\nimport type { GraphMetric } from \"./types.js\";\n\nconst DAY_SECONDS = 86400;\n\n/** Metric-name suffix for a window: `30d`, `180d`, or `lifetime`. */\nexport function windowSuffix(window: ChurnWindow): string {\n return window === \"lifetime\" ? \"lifetime\" : `${window}d`;\n}\n\n/**\n * Age-discount metrics: `recency_{w}` = min(1, age/w) for each file that churned\n * in window `w`, plus one window-independent `file_age_days` per file. Multiplying\n * a hotspot score by recency stops a young file's burst of churn from reading as\n * decay. Recency is emitted (as 1) even when the age is unknown, so a rule that\n * needs every hotspot factor is never silently disabled; `file_age_days` only when known.\n */\nexport function computeRecencyWindows(\n firstSeen: ReadonlyMap<string, number>,\n churnedIdsByWindow: ReadonlyMap<ChurnWindow, ReadonlySet<string>>,\n nowEpoch: number,\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n const ageEmitted = new Set<string>();\n for (const [windowDays, ids] of churnedIdsByWindow) {\n const suffix = windowSuffix(windowDays);\n for (const id of ids) {\n const seen = firstSeen.get(id);\n let recency = 1;\n if (seen !== undefined) {\n const ageDays = Math.max(0, (nowEpoch - seen) / DAY_SECONDS);\n // Lifetime has no window to age against, so its recency stays 1.\n if (windowDays !== \"lifetime\") recency = Math.min(1, ageDays / windowDays);\n if (!ageEmitted.has(id)) {\n out.push({ nodeId: id, name: \"file_age_days\", value: Math.round(ageDays), unit: \"days\" });\n ageEmitted.add(id);\n }\n }\n out.push({ nodeId: id, name: `recency_${suffix}`, value: round3(recency), unit: \"ratio\" });\n }\n }\n return out;\n}\n\nexport function round3(n: number): number {\n return Math.round(n * 1000) / 1000;\n}\n","import {\n aggregateChurnWindows,\n authorLinesByPath,\n computeOwnership,\n entriesWithin,\n loadChurnEntries,\n loadFileFirstSeen,\n type ChurnEntry,\n type ChurnWindow,\n type PathChurn,\n summarizeOwnership,\n} from \"./history/index.js\";\nimport { groupTestsBySource, type TestSourceLink } from \"./analysis/test-linker.js\";\nimport { computeRecencyWindows, round3, windowSuffix } from \"./history-recency.js\";\nimport type { GraphMetric, GraphNode } from \"./types.js\";\n\nexport interface HistoryMetricsOptions {\n /** Primary window: scopes ownership. Default 30. */\n churnWindowDays?: number;\n /** Windows to store churn and recency for; default {@link DEFAULT_CHURN_WINDOWS}, primary always included. */\n churnWindows?: number[];\n /** Also store an all-time `lifetime` window over full git history. */\n includeLifetime?: boolean;\n /** Epoch seconds that windows end at; defaults to the current time. */\n nowEpoch?: number;\n}\n\n/** Windows the dashboard switcher offers; churn is stored for each by default. */\nexport const DEFAULT_CHURN_WINDOWS = [30, 90, 180];\n\n/** De-duped, ascending windows including the primary, with `lifetime` last (widest) when requested. */\nexport function resolveChurnWindows(\n requested: number[] | undefined,\n primaryWindow: number,\n includeLifetime: boolean,\n): ChurnWindow[] {\n const base = requested && requested.length > 0 ? requested : DEFAULT_CHURN_WINDOWS;\n const finite = [...new Set([primaryWindow, ...base])].filter((w) => w > 0).sort((a, b) => a - b);\n return includeLifetime ? [...finite, \"lifetime\"] : finite;\n}\n\nexport interface LoadedHistory {\n metrics: GraphMetric[];\n /** Churn entries inside the primary window, which also scopes test-coverage linking and ownership. */\n primaryEntries: readonly ChurnEntry[];\n}\n\n/**\n * Git-history metrics for a snapshot's file nodes: churn and recency per window,\n * ownership for the primary window (and lifetime when requested). Node ids are\n * the history engine's repo-relative paths, because both are rooted at `idRoot`.\n * Returns [] when git or history is unavailable.\n */\nexport function buildHistoryMetrics(\n nodes: Iterable<GraphNode>,\n idRoot: string,\n options: HistoryMetricsOptions = {},\n): GraphMetric[] {\n return loadHistoryMetrics(nodes, idRoot, options)?.metrics ?? [];\n}\n\n/** {@link buildHistoryMetrics} plus the primary-window entries it read; null when git or history is unavailable. */\nexport function loadHistoryMetrics(\n nodes: Iterable<GraphNode>,\n idRoot: string,\n options: HistoryMetricsOptions = {},\n): LoadedHistory | null {\n const knownPaths = collectFileIds(nodes);\n const primaryWindow = options.churnWindowDays ?? 30;\n const windows = resolveChurnWindows(options.churnWindows, primaryWindow, options.includeLifetime === true);\n // Load the widest window once and slice it per window; lifetime sorts widest.\n const wide = loadChurnEntries({ repoRoot: idRoot, windowDays: windows[windows.length - 1]! });\n if (wide === null) return null;\n const nowEpoch = options.nowEpoch ?? Math.floor(Date.now() / 1000);\n const churnByWindow = aggregateChurnWindows(wide, windows, nowEpoch, knownPaths);\n const primaryEntries = windows.at(-1) === primaryWindow ? wide : entriesWithin(wide, primaryWindow, nowEpoch);\n const metrics = [\n ...churnMetrics(churnByWindow),\n ...ownershipMetrics(primaryEntries, primaryWindow, knownPaths),\n ...recencyMetrics(idRoot, churnByWindow, knownPaths, nowEpoch),\n ];\n // Lifetime ownership is the dominant owner over full history; `wide` is full history when lifetime is on.\n if (options.includeLifetime === true) metrics.push(...ownershipMetrics(wide, \"lifetime\", knownPaths));\n return { metrics, primaryEntries };\n}\n\nexport function collectFileIds(nodes: Iterable<GraphNode>): Set<string> {\n const out = new Set<string>();\n for (const n of nodes) {\n if (n.kind === \"file\") out.add(n.id);\n }\n return out;\n}\n\n/** Name one window's per-path churn as `churn_{w}`, `churn_{w}_commits`, `churn_{w}_authors`. */\nexport function churnMetrics(churnByWindow: ReadonlyMap<ChurnWindow, ReadonlyMap<string, PathChurn>>): GraphMetric[] {\n const out: GraphMetric[] = [];\n for (const [window, byPath] of churnByWindow) {\n const suffix = windowSuffix(window);\n for (const [nodeId, churn] of byPath) {\n out.push(\n { nodeId, name: `churn_${suffix}`, value: churn.lines, unit: \"lines\" },\n { nodeId, name: `churn_${suffix}_commits`, value: churn.commits, unit: \"count\" },\n { nodeId, name: `churn_${suffix}_authors`, value: churn.authors, unit: \"count\" },\n );\n }\n }\n return out;\n}\n\n/** Name ownership as `bus_factor_{w}` and `top_author_share_{w}` (rounded to 3 places). */\nexport function ownershipMetrics(\n entries: readonly ChurnEntry[],\n window: ChurnWindow,\n knownPaths?: ReadonlySet<string>,\n): GraphMetric[] {\n const suffix = windowSuffix(window);\n const out: GraphMetric[] = [];\n for (const [nodeId, owner] of computeOwnership(entries, { knownPaths })) {\n out.push(\n { nodeId, name: `bus_factor_${suffix}`, value: owner.busFactor, unit: \"count\" },\n { nodeId, name: `top_author_share_${suffix}`, value: round3(owner.topAuthorShare), unit: \"ratio\" },\n );\n }\n return out;\n}\n\nexport interface TestCoverageOwnershipOptions {\n /** Window named in the metric suffix. Default 30. */\n windowDays?: ChurnWindow;\n /** Coverage threshold for bus factor (default 0.5 = 50% of churn). */\n busFactorThreshold?: number;\n}\n\n/**\n * Bus-factor / top-author-share of the *test coverage* for each source, keyed\n * on the source node. Aggregates churn authorship across all test files linked\n * to a source (via the two-pass linker) and summarises it the same way as\n * production ownership — so a file can read as well-spread on production code\n * yet a single-author silo on its tests (or vice versa). Emitted only for\n * sources with at least one linked test that has churn in the window.\n */\nexport function computeTestCoverageOwnership(\n entries: readonly ChurnEntry[],\n links: readonly TestSourceLink[],\n options: TestCoverageOwnershipOptions = {},\n): GraphMetric[] {\n const suffix = windowSuffix(options.windowDays ?? 30);\n const testsBySource = groupTestsBySource(links);\n const testIds = new Set<string>();\n for (const tests of testsBySource.values()) {\n for (const t of tests) testIds.add(t);\n }\n const linesByTest = authorLinesByPath(entries, testIds);\n const out: GraphMetric[] = [];\n for (const [nodeId, tests] of testsBySource) {\n const summary = summarizeOwnership(mergeAuthorChurn(tests, linesByTest), options.busFactorThreshold);\n if (summary === null) continue;\n out.push(\n { nodeId, name: `test_bus_factor_${suffix}`, value: summary.busFactor, unit: \"count\" },\n { nodeId, name: `test_top_author_share_${suffix}`, value: round3(summary.topAuthorShare), unit: \"ratio\" },\n );\n }\n return out;\n}\n\n/** Sum per-author churn across a set of test files into one author tally. */\nfunction mergeAuthorChurn(\n tests: ReadonlySet<string>,\n linesByTest: ReadonlyMap<string, Map<string, number>>,\n): Map<string, number> {\n const byAuthor = new Map<string, number>();\n for (const testId of tests) {\n const fileAuthors = linesByTest.get(testId);\n if (!fileAuthors) continue;\n for (const [author, lines] of fileAuthors) {\n byAuthor.set(author, (byAuthor.get(author) ?? 0) + lines);\n }\n }\n return byAuthor;\n}\n\n/** Recency for files that churned in each window; an unknown first-seen date still yields recency 1. */\nfunction recencyMetrics(\n idRoot: string,\n churnByWindow: ReadonlyMap<ChurnWindow, ReadonlyMap<string, PathChurn>>,\n knownPaths: ReadonlySet<string>,\n nowEpoch: number,\n): GraphMetric[] {\n const churnedByWindow = new Map<ChurnWindow, ReadonlySet<string>>();\n for (const [window, byPath] of churnByWindow) {\n if (byPath.size > 0) churnedByWindow.set(window, new Set(byPath.keys()));\n }\n if (churnedByWindow.size === 0) return [];\n const firstSeen = loadFileFirstSeen({ repoRoot: idRoot, knownPaths }) ?? new Map<string, number>();\n return computeRecencyWindows(firstSeen, churnedByWindow, nowEpoch);\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport { computeMetrics } from \"./metrics.js\";\nimport { computeSourceMetrics } from \"./source-metrics.js\";\nimport { computeDeadCodeMetrics } from \"./analysis/dead-code.js\";\nimport { computeCallMetrics } from \"./analysis/call-metrics.js\";\nimport { computeGrowthRiskMetrics } from \"./analysis/growth-risk.js\";\nimport { fileId } from \"./extractors/ids.js\";\nimport { linkTestsToSources, testCoverageCountMetrics } from \"./analysis/test-linker.js\";\nimport { computeChangeCoupling, type ChurnEntry } from \"./history/index.js\";\nimport {\n collectFileIds,\n computeTestCoverageOwnership,\n loadHistoryMetrics,\n type HistoryMetricsOptions,\n} from \"./history-metrics.js\";\nimport type { GraphEdge, GraphMetric, GraphNode } from \"./types.js\";\n\nexport interface IndexerMetricsInput {\n nodes: Map<string, GraphNode>;\n edges: Map<string, GraphEdge>;\n /** Files (re)parsed this run — source metrics are computed fresh for these. */\n parsedFiles: ParsedFile[];\n /** Source metrics carried forward verbatim for reused (unchanged) files. */\n reusedSourceMetrics: GraphMetric[];\n idRoot: string;\n /** Git-history metrics (churn, recency, ownership); omitted means none. */\n history?: HistoryMetricsOptions;\n}\n\n/**\n * Map each file id to the names of the `symbol` nodes it declares, so\n * `computeSourceMetrics` can attach per-function complexity. Reflects the\n * assembled node set (parsed + reused symbol nodes alike), so per-symbol\n * complexity is emitted for exactly the names that have a symbol node.\n */\nfunction symbolNamesByFile(nodes: Iterable<GraphNode>): Map<string, Set<string>> {\n const out = new Map<string, Set<string>>();\n for (const n of nodes) {\n if (n.kind !== \"symbol\" || !n.parentId) continue;\n const bucket = out.get(n.parentId);\n if (bucket) bucket.add(n.name);\n else out.set(n.parentId, new Set([n.name]));\n }\n return out;\n}\n\n/**\n * Assemble the metric set for a snapshot: graph-wide degree metrics over the\n * full node/edge set, freshly-computed source metrics for (re)parsed files, and\n * reused source metrics carried forward for unchanged files. Everything but the\n * reused source metrics is recomputed over the full set, so the result matches a\n * full index regardless of how much was reused.\n *\n * Git-history metrics come from the path-based engine in `./history/` through\n * the `history-metrics.ts` adapter. Test-coverage metrics run with or without it.\n */\nexport function buildIndexerMetrics(input: IndexerMetricsInput): GraphMetric[] {\n const nodeList = [...input.nodes.values()];\n const history = input.history ? loadHistoryMetrics(nodeList, input.idRoot, input.history) : null;\n return [\n ...computeMetrics(nodeList, [...input.edges.values()]),\n ...computeCallMetrics(nodeList, input.edges.values()),\n ...computeSourceMetrics(\n input.parsedFiles,\n (p) => fileId(input.idRoot, p),\n symbolNamesByFile(nodeList),\n ),\n ...computeDeadCodeMetrics(input.parsedFiles, (p) => fileId(input.idRoot, p)),\n ...computeGrowthRiskMetrics(input.parsedFiles, (p) => fileId(input.idRoot, p)),\n ...input.reusedSourceMetrics,\n ...(history?.metrics ?? []),\n ...computeTestCoverage(nodeList, history?.primaryEntries ?? null, input.history?.churnWindowDays),\n ];\n}\n\n/**\n * Two-pass test↔source linker outputs: per-source coverage counts (always) and,\n * when churn is available, the bus-factor / top-author-share of each source's\n * test coverage. Path-convention links need no churn; co-edit supplementation\n * and the ownership split reuse the already-loaded churn entries.\n */\nfunction computeTestCoverage(\n nodes: readonly GraphNode[],\n entries: readonly ChurnEntry[] | null,\n windowDays: number | undefined,\n): GraphMetric[] {\n const coEditPairs = entries ? computeChangeCoupling(entries, { knownPaths: collectFileIds(nodes) }).pairs : [];\n const links = linkTestsToSources(nodes, coEditPairs);\n if (links.length === 0) return [];\n const out = testCoverageCountMetrics(links);\n if (entries) {\n out.push(...computeTestCoverageOwnership(entries, links, { windowDays }));\n }\n return out;\n}\n","import type { GraphEdge, GraphFragment, GraphNode } from \"./types.js\";\n\nexport interface ExtractAccumulator {\n nodes: Map<string, GraphNode>;\n edges: Map<string, GraphEdge>;\n}\n\n/**\n * JSON-encoded so ids containing the separator can't collide (paths may hold\n * spaces). Mirrors the `(snapshot_id, src_id, dst_id, kind)` edge primary key.\n */\nfunction edgeKey(edge: GraphEdge): string {\n return JSON.stringify([edge.srcId, edge.dstId, edge.kind]);\n}\n\n/** First fragment wins per id, so walk order decides shared nodes exactly as a full index would. */\nexport function mergeFragments(fragments: readonly GraphFragment[]): ExtractAccumulator {\n const nodes = new Map<string, GraphNode>();\n const edges = new Map<string, GraphEdge>();\n for (const fragment of fragments) {\n for (const node of fragment.nodes) if (!nodes.has(node.id)) nodes.set(node.id, node);\n for (const edge of fragment.edges) {\n const key = edgeKey(edge);\n if (!edges.has(key)) edges.set(key, edge);\n }\n }\n return { nodes, edges };\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport { collectDeclarations } from \"./declared-names.js\";\nimport { symbolId } from \"./extractors/ids.js\";\nimport type { IdAlias } from \"./types.js\";\n\n/** The first index version whose symbol ids carry the enclosing scopes (`f.ts#Job.run`, TP-182). */\nexport const QUALIFIED_SYMBOLS_SINCE = \"0.14.0\";\n\nfunction versionParts(version: string): number[] | null {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(version);\n return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;\n}\n\n/** True when a snapshot's index version wrote bare-name symbol ids; an unversioned snapshot counts as older. */\nexport function predatesQualifiedSymbols(indexVersion: string): boolean {\n const have = versionParts(indexVersion);\n if (!have) return true;\n const since = versionParts(QUALIFIED_SYMBOLS_SINCE)!;\n for (let i = 0; i < 3; i++) {\n if (have[i] !== since[i]) return have[i]! < since[i]!;\n }\n return false;\n}\n\n/**\n * Aliases from the bare-name symbol ids older index versions wrote (`f.ts#run`)\n * to the qualified ids that replaced them (`f.ts#Job.run`). Written only where\n * the mapping is unambiguous: exactly one qualified name in the file descends\n * from the bare name, and the bare id is not itself still a node. Where two\n * classes both define `run`, the old node merged them and no alias is recorded.\n */\nexport function qualifiedSymbolAliases(\n files: Iterable<{ fileId: string; file: ParsedFile }>,\n nodeIds: ReadonlySet<string>,\n): IdAlias[] {\n const out: IdAlias[] = [];\n for (const { fileId, file } of files) {\n for (const [name, qualified] of qualifiedByName(file)) {\n const oldId = symbolId(fileId, name);\n if (qualified.size !== 1 || nodeIds.has(oldId)) continue;\n const newId = symbolId(fileId, [...qualified][0]!);\n if (nodeIds.has(newId)) out.push({ oldId, newId, reason: \"requalify\" });\n }\n }\n return out;\n}\n\nfunction qualifiedByName(file: ParsedFile): Map<string, Set<string>> {\n const out = new Map<string, Set<string>>();\n for (const d of collectDeclarations(file)) {\n const bucket = out.get(d.name);\n if (bucket) bucket.add(d.qualifiedName);\n else out.set(d.name, new Set([d.qualifiedName]));\n }\n return out;\n}\n","export type {\n EdgeKind,\n FileFingerprint,\n GraphEdge,\n GraphFragment,\n GraphMetric,\n GraphNode,\n IdAlias,\n IdAliasReason,\n NodeKind,\n NodeRole,\n SnapshotRow,\n} from \"./types.js\";\n\nexport type { SnapshotInsert } from \"./store.js\";\nexport { CodeGraphStore, openCodeGraph } from \"./store.js\";\nexport { DOMAIN_DDL, FINDING_DDL, KIT, MIGRATIONS, SCHEMA_VERSION, SNAPSHOT_SCOPED_TABLES } from \"./schema.js\";\nexport type { PruneOptions, PrunePlan, PruneResult } from \"./prune.js\";\nexport { planPrune, runPrune } from \"./prune.js\";\n\nexport type { IndexOptions, IndexResult } from \"./indexer.js\";\nexport { INDEX_VERSION, indexPaths } from \"./indexer.js\";\n\nexport type { Extractor, ParsedFile } from \"@titan-design/code-parser\";\nexport { getLanguageFromPath, getSupportedLanguages, parseFile, shouldIncludeFile } from \"@titan-design/code-parser\";\n\nexport type { LanguageExtractorOptions } from \"./extractors/dispatch.js\";\nexport { LanguageExtractor } from \"./extractors/dispatch.js\";\nexport { PythonGraphExtractor } from \"./extractors/python-extractor.js\";\nexport type { TsMorphGraphExtractorOptions } from \"./extractors/ts-morph-extractor.js\";\nexport { TsMorphGraphExtractor } from \"./extractors/ts-morph-extractor.js\";\nexport { buildFileModuleNodes } from \"./extractors/file-nodes.js\";\nexport type { DeepAst, DeepAstInput, MemberInfo, ParamInfo } from \"./extractors/deep-ast.js\";\nexport { computeDeepAst } from \"./extractors/deep-ast.js\";\nexport {\n externalId,\n fileId,\n moduleId,\n packageId,\n parentModuleId,\n parseSymbolId,\n symbolId,\n SYMBOL_ID_SEP,\n} from \"./extractors/ids.js\";\n\nexport type { ReadFile, ReuseBasis, SourceLanguage } from \"./incremental.js\";\nexport { hashContent, readSourceFiles, structuralSignature } from \"./incremental.js\";\nexport { walkSourceFiles } from \"./file-walk.js\";\nexport { collectDeclaredNames, collectDeclaredSpans, type LineSpan } from \"./declared-names.js\";\nexport { edgeWeight, pruneDanglingReferences, resolveBarrelEdges } from \"./barrel-resolve.js\";\nexport { ALL_ROLES, annotateRoles, classifyRole, computeRoleHints } from \"./roles.js\";\nexport { isGeneratedByHeuristic, isGeneratedFile, loadGeneratedPatterns } from \"./generated.js\";\nexport { canonicalEdgeKind, canonicalMetricName, canonicalRole } from \"./aliases.js\";\nexport {\n buildAliases,\n detectGitHead,\n detectGitToplevel,\n detectRenames,\n isInsideGitRepo,\n resolveGitRef,\n} from \"./git-renames.js\";\nexport type { AliasChain, AliasChainInput, AliasLoader, AliasResolution } from \"./identity/alias-chain.js\";\nexport { createAliasChain } from \"./identity/alias-chain.js\";\nexport type { Lineage, LineageSnapshot, LineageStep } from \"./identity/lineage.js\";\nexport { ALIAS_BASE_ATTR, buildLineage, lineagePath } from \"./identity/lineage.js\";\nexport type { AliasChainOptions, PriorSnapshotOptions, ResolveAliasOptions } from \"./identity/store-identity.js\";\nexport { aliasChain, loadLineage, priorSnapshotForRef, resolveAlias } from \"./identity/store-identity.js\";\nexport { computeMetrics } from \"./metrics.js\";\nexport { computeSourceMetrics, SOURCE_METRIC_NAMES } from \"./source-metrics.js\";\nexport { SYMBOL_METRIC_NAMES } from \"./symbol-metrics.js\";\nexport { EXCEPTION_METRIC_NAMES } from \"./analysis/exception-handling.js\";\nexport { buildIndexerMetrics } from \"./index-metrics.js\";\nexport { computeDeadCodeMetrics, DEAD_CODE_METRIC_NAMES } from \"./analysis/dead-code.js\";\nexport { computeGrowthRiskMetrics, GROWTH_RISK_METRIC_NAMES } from \"./analysis/growth-risk.js\";\nexport type { LinkMethod, LinkTestsOptions, TestSourceLink } from \"./analysis/test-linker.js\";\nexport { groupTestsBySource, linkTestsToSources, testCoverageCountMetrics } from \"./analysis/test-linker.js\";\nexport type { IstanbulCoverage, SymbolSpan } from \"./analysis/coverage.js\";\nexport { attributeCoverage, COVERAGE_METRIC_NAME } from \"./analysis/coverage.js\";\n/**\n * The history adapter: it turns `./history`'s primitives into `GraphMetric` rows, so it\n * lives at the root rather than behind the `./history` seam, which speaks no graph types.\n */\nexport type { HistoryMetricsOptions, LoadedHistory, TestCoverageOwnershipOptions } from \"./history-metrics.js\";\nexport {\n computeTestCoverageOwnership,\n DEFAULT_CHURN_WINDOWS,\n loadHistoryMetrics,\n resolveChurnWindows,\n} from \"./history-metrics.js\";\nexport { computeRecencyWindows, windowSuffix } from \"./history-recency.js\";\nexport type { PageRankOptions, PageRankResult, PageRankRow } from \"./analysis/pagerank.js\";\nexport { computePageRank, getEdgeWeight } from \"./analysis/pagerank.js\";\nexport type { RelevanceOptions } from \"./analysis/relevance.js\";\nexport { computeRelevance } from \"./analysis/relevance.js\";\nexport type {\n ReferenceEdgeLite,\n SymbolConsumers,\n SymbolCouplingOptions,\n SymbolCouplingPair,\n} from \"./analysis/symbol-coupling.js\";\nexport { computeSymbolConsumers, computeSymbolCoupling } from \"./analysis/symbol-coupling.js\";\nexport type {\n PackageFlag,\n PackageLayer,\n PackageStats,\n PairCoupling,\n PairFlag,\n PartitionQualityInput,\n PartitionQualityResult,\n} from \"./analysis/partition-quality.js\";\nexport { computePartitionQuality, invertBuckets } from \"./analysis/partition-quality.js\";\nexport {\n snapshotPageRank,\n snapshotReferenceEdges,\n snapshotRelevance,\n snapshotSymbolConsumers,\n snapshotSymbolCoupling,\n} from \"./analysis/snapshot.js\";\n\n/** Convenience readers over one snapshot; the store carries the full query surface. */\nexport { listEdges, listMetrics, listNodes } from \"./read.js\";\nexport type { MetricAggregate, TopMetricRow } from \"./store-reads.js\";\nexport { aggregateMetrics, listEdgesTouching, listMetricsForNode } from \"./read.js\";\nexport type {\n MetricAbsence,\n MetricDescriptor,\n MetricDirection,\n MetricRollup,\n MetricSource,\n MetricUnit,\n} from \"./catalogue/types.js\";\nexport { METRIC_CATALOGUE } from \"./catalogue/entries.js\";\nexport { describeMetric, describeMetrics } from \"./catalogue/describe.js\";\n\nexport type {\n CheckResult,\n CheckRule,\n CheckRulesFile,\n CheckViolation,\n ForbidImportRule,\n LayeredDepsRule,\n MetricMaxRule,\n MetricMinRule,\n MetricOutlierRule,\n MetricProductMaxRule,\n NoInternalOnlyBarrelsRule,\n Severity,\n} from \"./check/types.js\";\nexport type { RunChecksOptions } from \"./check/check.js\";\nexport { rebasedViolationKey, runChecks, snapshotViolations, violationKey } from \"./check/check.js\";\nexport type { RuleStore } from \"./check/context.js\";\nexport type { ExternalDiagnostic, Finding } from \"./check/findings.js\";\nexport { externalToFinding, toFindings } from \"./check/findings.js\";\nexport type {\n FindingKeyInput,\n StoredFinding,\n StoredVerdict,\n VerdictCitation,\n VerdictLabel,\n} from \"./check/finding-store.js\";\nexport {\n carryForwardVerdicts,\n findingKey,\n hashText,\n keyFindings,\n listFindings,\n listVerdicts,\n normalizeFlaggedText,\n saveFindings,\n saveVerdicts,\n} from \"./check/finding-store.js\";\nexport { compilePatterns, matchesAny, patternToRegex } from \"./check/patterns.js\";\nexport type { ValidateRulesOptions } from \"./check/validate.js\";\nexport { validateRules } from \"./check/validate.js\";\nexport { DEFAULT_OUTLIER_MIN_SAMPLE, percentileOf } from \"./check/outlier-rule.js\";\nexport type { CheckSnapshotOptions, CheckSnapshotResult, SnapshotSpec } from \"./check/run.js\";\nexport { checkSnapshot, loadCheckRules, resolveSnapshot } from \"./check/run.js\";\n\nexport type { GraphDiff, GraphDiffSummary, MetricDelta, NodeRename } from \"./diff/types.js\";\nexport type { DiffSnapshotsOptions } from \"./diff/diff.js\";\nexport { diffSnapshots } from \"./diff/diff.js\";\nexport type { CheckDiff, DiffCheckResultsOptions, UnchangedViolation } from \"./diff/check-diff.js\";\nexport { diffCheckResults } from \"./diff/check-diff.js\";\nexport type {\n FootprintGraph,\n FootprintOptions,\n FootprintParts,\n FootprintUnit,\n SymbolFootprint,\n} from \"./diff/footprint.js\";\nexport { computeFootprints, symbolSetHash } from \"./diff/footprint.js\";\n\nexport type {\n EmbedAttempt,\n EmbedCoverage,\n EmbeddableSymbol,\n EmbedSnapshotResult,\n FindSimilarOptions,\n SimilarCandidate,\n SimilarResult,\n} from \"./embeddings/types.js\";\nexport { buildEmbedText, hashEmbedText, listEmbeddableSymbols } from \"./embeddings/corpus.js\";\nexport type { CachedEmbedResult } from \"./embeddings/cache.js\";\nexport { embedTextsCached, SYMBOL_EMBEDDING_NAMESPACE } from \"./embeddings/cache.js\";\nexport { embedSnapshot, findSimilarCapability, tryEmbedSnapshot } from \"./embeddings/embeddings.js\";\n\nexport type {\n ConventionArea,\n ConventionCorpus,\n ConventionCoverage,\n ConventionMap,\n ConventionMatch,\n ConventionOptions,\n ConventionQueryResult,\n ConventionSymbol,\n FindConventionsOptions,\n SummarizeConventionsResult,\n Summarizer,\n} from \"./conventions/types.js\";\nexport { detectCommunities } from \"./conventions/communities.js\";\nexport { buildConventionAreas, defaultTargetCount } from \"./conventions/areas.js\";\nexport { COMMUNITY_SUMMARY_NAMESPACE, getConventionMap, summarizeConventions } from \"./conventions/summaries.js\";\nexport { findConventions } from \"./conventions/query.js\";\n","import { readFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n Node,\n Project,\n ScriptTarget,\n type ArrowFunction,\n type ClassDeclaration,\n type FunctionDeclaration,\n type FunctionExpression,\n type InterfaceDeclaration,\n type MethodDeclaration,\n type SourceFile,\n} from \"ts-morph\";\nimport { declarationText, lookupDeclaration } from \"./symbol-signature.js\";\n\n/**\n * C-81 — **deep AST on-pull**. Structural facts too heavy to persist at index\n * time (class members, per-parameter types, return type) are recomputed lazily\n * here from the working-tree source when a consumer actually pulls a target.\n * Persisting them would bloat every symbol node and break the incremental reuse\n * basis (inferred types embed absolute `import(\"…\")` paths); computing on demand\n * keeps the index lean while still answering \"what are the members / params of\n * this\" for the one target being read.\n *\n * A single-file in-memory ts-morph project (no tsconfig, no dependency walk) —\n * so the extraction is cheap and reads only explicit syntactic annotations.\n */\nexport interface ParamInfo {\n name: string;\n type: string | null;\n}\n\nexport interface MemberInfo {\n name: string;\n memberKind: string;\n signature: string | null;\n isStatic: boolean;\n}\n\nexport interface DeepAst {\n target: string;\n kind: \"file\" | \"symbol\";\n declarationKind: string | null;\n signature: string | null;\n purpose: string | null;\n params: ParamInfo[];\n returnType: string | null;\n /** Class/interface members for a symbol; exported declarations for a file. */\n members: MemberInfo[];\n note?: string;\n}\n\nexport interface DeepAstInput {\n /** Repo-relative file id, e.g. `src/a.ts`. */\n filePath: string;\n /** Absolute path to the file on disk. */\n absPath: string;\n /** Symbol name for a symbol target; omit for a file target. */\n symbolName?: string;\n}\n\ntype Callable =\n | FunctionDeclaration\n | MethodDeclaration\n | ArrowFunction\n | FunctionExpression;\n\n/** Deep structural facts for one target, or null when the source is unreadable. */\nexport function computeDeepAst(input: DeepAstInput): DeepAst | null {\n const sf = loadSourceFile(input.absPath);\n if (!sf) return null;\n const target = input.symbolName\n ? `${input.filePath}#${input.symbolName}`\n : input.filePath;\n return input.symbolName\n ? symbolDeepAst(sf, input.symbolName, target)\n : fileDeepAst(sf, target);\n}\n\nfunction loadSourceFile(absPath: string): SourceFile | null {\n try {\n const text = readFileSync(absPath, \"utf8\");\n const project = new Project({\n useInMemoryFileSystem: true,\n compilerOptions: { target: ScriptTarget.Latest, allowJs: true },\n });\n return project.createSourceFile(`f${path.extname(absPath) || \".ts\"}`, text);\n } catch {\n return null;\n }\n}\n\nfunction symbolDeepAst(sf: SourceFile, name: string, target: string): DeepAst {\n const decl = lookupDeclaration(sf, name);\n if (!decl) {\n return { ...empty(target, \"symbol\"), note: \"declaration not found in source\" };\n }\n const text = declarationText(decl);\n return {\n target,\n kind: \"symbol\",\n declarationKind: decl.getKindName(),\n signature: text.signature ?? null,\n purpose: text.purpose ?? null,\n params: paramsOf(decl),\n returnType: returnTypeOf(decl),\n members: membersOf(decl),\n };\n}\n\nfunction fileDeepAst(sf: SourceFile, target: string): DeepAst {\n return {\n ...empty(target, \"file\"),\n declarationKind: \"SourceFile\",\n members: exportedDeclarations(sf),\n };\n}\n\nfunction empty(target: string, kind: \"file\" | \"symbol\"): DeepAst {\n return {\n target,\n kind,\n declarationKind: null,\n signature: null,\n purpose: null,\n params: [],\n returnType: null,\n members: [],\n };\n}\n\n/** Unwrap a declaration to the callable it defines, or null for non-callables. */\nfunction callableOf(decl: Node): Callable | null {\n if (Node.isFunctionDeclaration(decl) || Node.isMethodDeclaration(decl)) return decl;\n if (Node.isVariableDeclaration(decl)) {\n const init = decl.getInitializer();\n if (init && (Node.isArrowFunction(init) || Node.isFunctionExpression(init))) return init;\n }\n return null;\n}\n\nfunction paramsOf(decl: Node): ParamInfo[] {\n const callable = callableOf(decl);\n if (!callable) return [];\n return callable.getParameters().map((p) => ({\n name: p.getName(),\n type: p.getTypeNode()?.getText() ?? null,\n }));\n}\n\nfunction returnTypeOf(decl: Node): string | null {\n return callableOf(decl)?.getReturnTypeNode()?.getText() ?? null;\n}\n\nfunction membersOf(decl: Node): MemberInfo[] {\n if (Node.isClassDeclaration(decl)) return classMembers(decl);\n if (Node.isInterfaceDeclaration(decl)) return interfaceMembers(decl);\n return [];\n}\n\nfunction classMembers(cls: ClassDeclaration): MemberInfo[] {\n return cls.getMembers().map((m) => ({\n name: memberName(m),\n memberKind: m.getKindName(),\n signature: memberSignature(m),\n isStatic: Node.isStaticable(m) ? m.isStatic() : false,\n }));\n}\n\nfunction interfaceMembers(iface: InterfaceDeclaration): MemberInfo[] {\n return iface.getMembers().map((m) => ({\n name: memberName(m),\n memberKind: m.getKindName(),\n signature: memberSignature(m),\n isStatic: false,\n }));\n}\n\nfunction exportedDeclarations(sf: SourceFile): MemberInfo[] {\n const out: MemberInfo[] = [];\n for (const [name, decls] of sf.getExportedDeclarations()) {\n const decl = decls[0];\n if (!decl) continue;\n out.push({\n name,\n memberKind: decl.getKindName(),\n signature: declarationText(decl).signature ?? memberSignature(decl),\n isStatic: false,\n });\n }\n return out;\n}\n\nfunction memberName(m: Node): string {\n if (Node.isConstructorDeclaration(m)) return \"constructor\";\n return Node.hasName(m) ? m.getName() : \"\";\n}\n\nfunction memberSignature(m: Node): string | null {\n if (\n Node.isMethodDeclaration(m) ||\n Node.isMethodSignature(m) ||\n Node.isConstructorDeclaration(m)\n ) {\n const params = m.getParameters().map((p) => oneLine(p.getText())).join(\", \");\n const ret = m.getReturnTypeNode()?.getText();\n const name = Node.isConstructorDeclaration(m) ? \"constructor\" : memberName(m);\n return oneLine(`${name}(${params})${ret ? `: ${ret}` : \"\"}`);\n }\n if (Node.isPropertyDeclaration(m) || Node.isPropertySignature(m)) {\n const type = m.getTypeNode()?.getText();\n return oneLine(`${memberName(m)}${type ? `: ${type}` : \"\"}`);\n }\n return null;\n}\n\nfunction oneLine(s: string): string {\n return s.replace(/\\s+/g, \" \").trim();\n}\n","import type { EdgeKind, NodeRole } from \"./types.js\";\n\n/**\n * Schema-healing aliases: deprecated or synonymous spellings mapped to the one\n * canonical name codewatch emits today. Two jobs:\n *\n * 1. Rename tolerance on snapshot diff — a metric/edge-kind renamed between an\n * old snapshot and a new one is reconciled to its canonical name so it\n * lines up instead of surfacing as a spurious add/remove.\n * 2. Config tolerance — an external `.codewatch/check.json` that spells a\n * metric or role with a separator/plural variant loads with a deprecation\n * warning and the canonical name, not a hard error.\n *\n * Seeds are conservative: only separator (`-`/`_`), singular/plural, and\n * unambiguous synonym variants of names codewatch actually produces. Add a real\n * historical rename here when one lands; nothing maps a name to a *different*\n * concept.\n */\n\nconst METRIC_ALIASES: ReadonlyMap<string, string> = new Map([\n [\"lines\", \"loc\"],\n [\"lines_of_code\", \"loc\"],\n [\"fan-in\", \"fan_in\"],\n [\"fanin\", \"fan_in\"],\n [\"fan-out\", \"fan_out\"],\n [\"fanout\", \"fan_out\"],\n [\"nesting_depth\", \"max_nesting_depth\"],\n [\"max-nesting-depth\", \"max_nesting_depth\"],\n [\"lcom4\", \"lcom4_max\"],\n]);\n\nconst ROLE_ALIASES: ReadonlyMap<string, string> = new Map([\n [\"tests\", \"test\"],\n [\"spec\", \"test\"],\n [\"specs\", \"test\"],\n [\"fixtures\", \"fixture\"],\n [\"barrels\", \"barrel\"],\n]);\n\nconst EDGE_KIND_ALIASES: ReadonlyMap<string, string> = new Map([\n [\"import\", \"imports\"],\n [\"call\", \"calls\"],\n [\"reference\", \"references\"],\n [\"re_exports\", \"re-exports\"],\n [\"reexports\", \"re-exports\"],\n [\"re-export\", \"re-exports\"],\n [\"depends_on\", \"depends-on\"],\n [\"dependson\", \"depends-on\"],\n]);\n\n/** Canonical name for a deprecated alias, or `undefined` if `name` is not aliased. */\nexport function deprecatedTarget(\n map: ReadonlyMap<string, string>,\n name: string,\n): string | undefined {\n return map.get(name);\n}\n\nexport function canonicalMetricName(name: string): string {\n return METRIC_ALIASES.get(name) ?? name;\n}\n\nexport function canonicalRole(name: string): NodeRole {\n return (ROLE_ALIASES.get(name) ?? name) as NodeRole;\n}\n\nexport function canonicalEdgeKind(name: string): EdgeKind {\n return (EDGE_KIND_ALIASES.get(name) ?? name) as EdgeKind;\n}\n\n/** Canonical metric name for a deprecated alias, or `undefined`. */\nexport function metricAliasTarget(name: string): string | undefined {\n return deprecatedTarget(METRIC_ALIASES, name);\n}\n\n/** Canonical role for a deprecated alias, or `undefined`. */\nexport function roleAliasTarget(name: string): NodeRole | undefined {\n return deprecatedTarget(ROLE_ALIASES, name) as NodeRole | undefined;\n}\n","import type { GraphMetric } from \"../types.js\";\n\n/**\n * Coverage is a whole-suite DYNAMIC artifact — a function of *which tests ran*,\n * not of any file's bytes — so it must NOT ride the content-hash reuse gate. It\n * is emitted as a `coverage_pct` metric that is deliberately absent from every\n * *_METRIC_NAMES reuse set, so an incremental index never carries it forward: a\n * later index produces a snapshot with NO coverage until re-ingested. That is the\n * overlay semantics — coverage is attached to the snapshot it was measured\n * against and never inferred for another.\n */\nexport const COVERAGE_METRIC_NAME = \"coverage_pct\";\n\n/** Minimal Istanbul `coverage-final.json` shape we read (function-level). */\ninterface IstanbulFn {\n loc: { start: { line: number }; end: { line: number } };\n}\ninterface IstanbulFileCoverage {\n fnMap: Record<string, IstanbulFn>;\n /** Per-function hit counts, keyed to fnMap ids. */\n f: Record<string, number>;\n}\nexport type IstanbulCoverage = Record<string, IstanbulFileCoverage>;\n\n/** A symbol node's 1-based line span, for range-containment attribution. */\nexport interface SymbolSpan {\n id: string;\n startLine: number;\n endLine: number;\n}\n\nfunction isFileCoverage(v: unknown): v is IstanbulFileCoverage {\n return (\n typeof v === \"object\" &&\n v !== null &&\n typeof (v as IstanbulFileCoverage).fnMap === \"object\" &&\n typeof (v as IstanbulFileCoverage).f === \"object\"\n );\n}\n\n/** The smallest-span symbol whose 1-based range contains `line`, or null. */\nfunction innermostContaining(symbols: readonly SymbolSpan[], line: number): SymbolSpan | null {\n let best: SymbolSpan | null = null;\n for (const s of symbols) {\n if (s.startLine <= line && line <= s.endLine) {\n if (!best || s.endLine - s.startLine < best.endLine - best.startLine) best = s;\n }\n }\n return best;\n}\n\n/**\n * Attribute an Istanbul coverage report to graph nodes as `coverage_pct` metrics:\n * one per covered FILE (covered functions / total functions), and one per SYMBOL\n * a covered function maps into by RANGE containment (symbol spans) — matching\n * by range, not name, so anonymous/mangled Istanbul function names are handled.\n * A symbol spanning several functions (a class) reports its methods' coverage\n * ratio. Files Istanbul reports but the graph doesn't know are skipped.\n */\nexport function attributeCoverage(\n coverage: IstanbulCoverage,\n fileIdOf: (absPath: string) => string | null,\n symbolsByFile: ReadonlyMap<string, readonly SymbolSpan[]>,\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n for (const [absPath, fc] of Object.entries(coverage)) {\n if (!isFileCoverage(fc)) continue;\n const fileId = fileIdOf(absPath);\n if (!fileId) continue;\n const fnIds = Object.keys(fc.fnMap);\n if (fnIds.length === 0) continue;\n\n const covered = fnIds.filter((k) => (fc.f[k] ?? 0) > 0).length;\n out.push(pctMetric(fileId, covered, fnIds.length));\n out.push(...symbolCoverage(fc, fnIds, symbolsByFile.get(fileId) ?? []));\n }\n return out;\n}\n\nfunction symbolCoverage(fc: IstanbulFileCoverage, fnIds: readonly string[], symbols: readonly SymbolSpan[]): GraphMetric[] {\n const perSymbol = new Map<string, { hit: number; total: number }>();\n for (const k of fnIds) {\n const sym = innermostContaining(symbols, fc.fnMap[k]!.loc.start.line);\n if (!sym) continue;\n const acc = perSymbol.get(sym.id) ?? { hit: 0, total: 0 };\n acc.total++;\n if ((fc.f[k] ?? 0) > 0) acc.hit++;\n perSymbol.set(sym.id, acc);\n }\n return [...perSymbol].map(([id, { hit, total }]) => pctMetric(id, hit, total));\n}\n\nfunction pctMetric(nodeId: string, covered: number, total: number): GraphMetric {\n return {\n nodeId,\n name: COVERAGE_METRIC_NAME,\n value: Math.round((100 * covered) / total),\n unit: \"percent\",\n };\n}\n","import type { EdgeKind, GraphEdge, GraphNode } from \"../types.js\";\n\nexport interface PageRankOptions {\n /** Per-node teleport weight. Unset or empty → uniform teleport across all nodes. */\n personalization?: ReadonlyMap<string, number>;\n /** Probability of following an edge vs teleporting (default 0.85). */\n damping?: number;\n /** L1 convergence threshold (default 1e-6). */\n tolerance?: number;\n /** Cap on power-iteration steps (default 100). */\n maxIterations?: number;\n /** Per-kind edge weight; missing kinds default to 1.0. */\n edgeWeights?: Partial<Record<EdgeKind, number>>;\n}\n\nexport interface PageRankRow {\n nodeId: string;\n score: number;\n}\n\nexport interface PageRankResult {\n /** Sorted descending by score; ties broken by node id ascending. */\n rows: PageRankRow[];\n iterations: number;\n converged: boolean;\n}\n\nconst DEFAULT_DAMPING = 0.85;\nconst DEFAULT_TOLERANCE = 1e-6;\nconst DEFAULT_MAX_ITERS = 100;\n\nconst DEFAULT_EDGE_WEIGHTS: Record<EdgeKind, number> = {\n imports: 1.0,\n \"re-exports\": 0.5,\n calls: 1.5,\n extends: 1.0,\n implements: 1.0,\n references: 1.0,\n \"depends-on\": 1.0,\n};\n\n/** Edge weight used by PageRank for a given edge kind, honoring user overrides. */\nexport function getEdgeWeight(\n kind: EdgeKind,\n overrides?: Partial<Record<EdgeKind, number>>,\n): number {\n return overrides?.[kind] ?? DEFAULT_EDGE_WEIGHTS[kind] ?? 1.0;\n}\n\ninterface Adjacency {\n outNeighbors: Array<Array<{ to: number; w: number }>>;\n outWeightSum: number[];\n}\n\nexport function computePageRank(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n options: PageRankOptions = {},\n): PageRankResult {\n const n = nodes.length;\n if (n === 0) return { rows: [], iterations: 0, converged: true };\n\n const damping = options.damping ?? DEFAULT_DAMPING;\n const tolerance = options.tolerance ?? DEFAULT_TOLERANCE;\n const maxIters = options.maxIterations ?? DEFAULT_MAX_ITERS;\n const weights = { ...DEFAULT_EDGE_WEIGHTS, ...(options.edgeWeights ?? {}) };\n\n const idx = buildIdIndex(nodes);\n const adj = buildAdjacency(idx, edges, weights, n);\n const pers = buildPersonalization(idx, n, options.personalization);\n\n const { rank, iterations, converged } = powerIterate(\n pers,\n adj,\n damping,\n tolerance,\n maxIters,\n );\n\n return { rows: rankToRows(nodes, rank), iterations, converged };\n}\n\nfunction buildIdIndex(nodes: readonly GraphNode[]): Map<string, number> {\n const idx = new Map<string, number>();\n for (let i = 0; i < nodes.length; i++) idx.set(nodes[i]!.id, i);\n return idx;\n}\n\nfunction buildAdjacency(\n idx: ReadonlyMap<string, number>,\n edges: readonly GraphEdge[],\n weights: Record<EdgeKind, number>,\n n: number,\n): Adjacency {\n const outNeighbors: Array<Array<{ to: number; w: number }>> = Array.from(\n { length: n },\n () => [],\n );\n const outWeightSum = new Array<number>(n).fill(0);\n for (const e of edges) {\n const si = idx.get(e.srcId);\n const di = idx.get(e.dstId);\n if (si === undefined || di === undefined) continue;\n const w = weights[e.kind] ?? 1.0;\n if (w <= 0) continue;\n outNeighbors[si]!.push({ to: di, w });\n outWeightSum[si]! += w;\n }\n return { outNeighbors, outWeightSum };\n}\n\nfunction powerIterate(\n pers: readonly number[],\n adj: Adjacency,\n damping: number,\n tolerance: number,\n maxIters: number,\n): { rank: number[]; iterations: number; converged: boolean } {\n const n = pers.length;\n let rank = pers.slice();\n let next = new Array<number>(n).fill(0);\n let iterations = 0;\n let converged = false;\n for (let iter = 0; iter < maxIters; iter++) {\n iterations = iter + 1;\n const dangling = sumDangling(rank, adj.outWeightSum);\n const teleport = 1 - damping + damping * dangling;\n seedTeleport(next, pers, teleport);\n distributeRank(next, rank, adj, damping);\n const diff = l1Diff(rank, next);\n [rank, next] = [next, rank];\n next.fill(0);\n if (diff < tolerance) {\n converged = true;\n break;\n }\n }\n return { rank, iterations, converged };\n}\n\nfunction sumDangling(\n rank: readonly number[],\n outWeightSum: readonly number[],\n): number {\n let total = 0;\n for (let i = 0; i < rank.length; i++) {\n if (outWeightSum[i] === 0) total += rank[i]!;\n }\n return total;\n}\n\nfunction seedTeleport(\n next: number[],\n pers: readonly number[],\n teleport: number,\n): void {\n for (let i = 0; i < next.length; i++) next[i] = teleport * pers[i]!;\n}\n\nfunction distributeRank(\n next: number[],\n rank: readonly number[],\n adj: Adjacency,\n damping: number,\n): void {\n for (let i = 0; i < rank.length; i++) {\n const s = adj.outWeightSum[i]!;\n if (s === 0 || rank[i]! === 0) continue;\n const factor = (damping * rank[i]!) / s;\n const list = adj.outNeighbors[i]!;\n for (let k = 0; k < list.length; k++) {\n next[list[k]!.to]! += factor * list[k]!.w;\n }\n }\n}\n\nfunction l1Diff(a: readonly number[], b: readonly number[]): number {\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff += Math.abs(b[i]! - a[i]!);\n return diff;\n}\n\nfunction rankToRows(\n nodes: readonly GraphNode[],\n rank: readonly number[],\n): PageRankRow[] {\n return nodes\n .map((node, i) => ({ nodeId: node.id, score: rank[i]! }))\n .sort(compareRows);\n}\n\nfunction compareRows(a: PageRankRow, b: PageRankRow): number {\n if (b.score !== a.score) return b.score - a.score;\n return a.nodeId < b.nodeId ? -1 : a.nodeId > b.nodeId ? 1 : 0;\n}\n\nfunction buildPersonalization(\n idx: ReadonlyMap<string, number>,\n n: number,\n pers: PageRankOptions[\"personalization\"],\n): number[] {\n if (!pers || pers.size === 0) return uniformVector(n);\n const out = new Array<number>(n).fill(0);\n const total = applySeedWeights(out, idx, pers);\n if (total === 0) return uniformVector(n);\n for (let i = 0; i < n; i++) out[i]! /= total;\n return out;\n}\n\nfunction uniformVector(n: number): number[] {\n return new Array<number>(n).fill(1 / n);\n}\n\nfunction applySeedWeights(\n out: number[],\n idx: ReadonlyMap<string, number>,\n pers: NonNullable<PageRankOptions[\"personalization\"]>,\n): number {\n let total = 0;\n for (const [id, w] of pers) {\n if (!isValidWeight(w)) continue;\n const i = idx.get(id);\n if (i === undefined) continue;\n out[i] = w;\n total += w;\n }\n return total;\n}\n\nfunction isValidWeight(w: number): boolean {\n return Number.isFinite(w) && w > 0;\n}\n","import { computePageRank, type PageRankOptions } from \"./pagerank.js\";\nimport type { GraphEdge, GraphNode } from \"../types.js\";\n\nexport interface RelevanceOptions {\n /** Probability of following an edge vs teleporting back to the seeds (default 0.85). */\n damping?: number;\n /** Per-kind edge weight override, forwarded to PageRank. */\n edgeWeights?: PageRankOptions[\"edgeWeights\"];\n}\n\n/**\n * C-89 — **seeded (personalized) PageRank as a relevance-to-target proximity\n * measure** (Aider RepoMap-style). The teleport vector is concentrated on\n * `seedIds`, so the stationary distribution scores every node by how tightly it\n * couples to the seeds through the resolved dependency graph: near neighbours\n * score high, decaying with graph distance. This is \"relevance to what I'm\n * looking at,\" distinct from global PageRank centrality (\"globally famous\"),\n * which stays the no-seed cold path.\n *\n * The edge set is **symmetrized** (each edge added in both directions) so\n * relevance flows to a target's callers AND its dependencies — a purely forward\n * walk from the seed would only reach what the seed depends on, never who\n * depends on it. Edge kind (and therefore weight) is preserved on the reversed\n * copy, so a heavier `calls` edge stays heavier in both directions.\n *\n * Returns a Map from node id to relevance score (seeds included). An empty seed\n * set returns an empty map — callers then fall back to global centrality.\n */\nexport function computeRelevance(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n seedIds: readonly string[],\n options: RelevanceOptions = {},\n): Map<string, number> {\n const seeds = seedIds.filter((id) => id.length > 0);\n if (seeds.length === 0) return new Map();\n const personalization = new Map(seeds.map((id) => [id, 1] as const));\n const result = computePageRank(nodes, symmetrize(edges), {\n personalization,\n damping: options.damping,\n edgeWeights: options.edgeWeights,\n });\n const out = new Map<string, number>();\n for (const row of result.rows) out.set(row.nodeId, row.score);\n return out;\n}\n\n/** Every edge plus its reverse, so the relevance walk is bidirectional. */\nfunction symmetrize(edges: readonly GraphEdge[]): GraphEdge[] {\n const out: GraphEdge[] = [];\n for (const e of edges) {\n out.push(e);\n out.push({ ...e, srcId: e.dstId, dstId: e.srcId });\n }\n return out;\n}\n","import { parseSymbolId } from \"../extractors/ids.js\";\n\n/**\n * Symbol-level change coupling (C-60). Decomposes a god-file the file-level\n * coupling view rolls up as one blob (e.g. `types.ts`) into *which symbol* is\n * used where. Built on the C-53 `references` edge substrate: `src` is the\n * importing file, `dst` is the imported symbol node id (`<fileId>#<name>`).\n *\n * Two slices, both pure functions of the assembled reference edge set (a\n * whole-graph rollup like utilization/PageRank, sound under incremental reuse\n * since it reads the reassembled edges, not a per-file cache):\n *\n * - **Slice C — per-symbol consumers**: invert the edges by `dst`, giving the\n * set of files that import each symbol. Directly answers \"what IN this file is\n * used where\"; covers span-less types/consts that a git-hunk approach cannot.\n * - **Slice B — co-import coupling**: group edges by `src`, and every pair of\n * symbols co-imported by the same file is a coupling pair. Two symbols that\n * are always imported together travel together — structural (used-together),\n * drift-free coupling, as opposed to the temporal (changed-together) git\n * co-edit signal.\n */\n\n/** The minimal shape of a `references` edge this module consumes. */\nexport interface ReferenceEdgeLite {\n /** Importing file id. */\n srcId: string;\n /** Imported symbol node id (`<fileId>#<name>`). */\n dstId: string;\n}\n\n/** One symbol's consumer set (Slice C). */\nexport interface SymbolConsumers {\n symbolId: string;\n /** Declaring file, parsed from the symbol id. */\n fileId: string;\n /** Export name. */\n name: string;\n /** Distinct importing file ids, sorted. */\n consumers: string[];\n}\n\n/** A pair of symbols co-imported by the same file (Slice B). */\nexport interface SymbolCouplingPair {\n aId: string;\n aFile: string;\n aName: string;\n bId: string;\n bFile: string;\n bName: string;\n /** Distinct files that import both symbols. */\n coImports: number;\n /** True when the two symbols are declared in different files. */\n crossFile: boolean;\n}\n\nexport interface SymbolCouplingOptions {\n /** Skip pairs co-imported by fewer than this many files. Default 2. */\n minCoImports?: number;\n /**\n * Skip importing files that reference more than this many distinct symbols —\n * a wide barrel-style importer would otherwise explode into O(n²) noise\n * pairs, mirroring change-coupling's large-commit guard. Default 40.\n */\n largeImporterThreshold?: number;\n}\n\nconst DEFAULT_MIN_CO_IMPORTS = 2;\nconst DEFAULT_LARGE_IMPORTER_THRESHOLD = 40;\n\n/**\n * Group reference edges by imported symbol, yielding each symbol's distinct\n * consuming files (Slice C). Sorted by consumer count desc, then symbol id, so\n * the most broadly-depended-on exports lead.\n */\nexport function computeSymbolConsumers(\n edges: readonly ReferenceEdgeLite[],\n): SymbolConsumers[] {\n const bySymbol = new Map<string, Set<string>>();\n for (const e of edges) {\n let set = bySymbol.get(e.dstId);\n if (!set) {\n set = new Set();\n bySymbol.set(e.dstId, set);\n }\n set.add(e.srcId);\n }\n const out: SymbolConsumers[] = [];\n for (const [id, consumers] of bySymbol) {\n const parsed = parseSymbolId(id);\n if (!parsed) continue;\n out.push({\n symbolId: id,\n fileId: parsed.fileId,\n name: parsed.name,\n consumers: [...consumers].sort(),\n });\n }\n return out.sort(compareConsumers);\n}\n\nfunction compareConsumers(a: SymbolConsumers, b: SymbolConsumers): number {\n if (b.consumers.length !== a.consumers.length) {\n return b.consumers.length - a.consumers.length;\n }\n return a.symbolId < b.symbolId ? -1 : a.symbolId > b.symbolId ? 1 : 0;\n}\n\n/**\n * Every pair of symbols co-imported by the same file becomes a coupling pair,\n * counted by how many distinct files co-import them (Slice B). Wide importers\n * are dropped to keep the pairing near-linear. Sorted by co-import count desc,\n * cross-file pairs preferred at a tie (they are the actionable ones — a\n * same-file pair is just cohesion within one module).\n */\nexport function computeSymbolCoupling(\n edges: readonly ReferenceEdgeLite[],\n options: SymbolCouplingOptions = {},\n): SymbolCouplingPair[] {\n const minCoImports = options.minCoImports ?? DEFAULT_MIN_CO_IMPORTS;\n const largeThreshold =\n options.largeImporterThreshold ?? DEFAULT_LARGE_IMPORTER_THRESHOLD;\n const bySource = groupSymbolsBySource(edges);\n const counts = new Map<string, number>();\n for (const symbols of bySource.values()) {\n if (symbols.length < 2 || symbols.length > largeThreshold) continue;\n accumulateSymbolPairs(symbols, counts);\n }\n return finalizePairs(counts, minCoImports);\n}\n\nfunction groupSymbolsBySource(\n edges: readonly ReferenceEdgeLite[],\n): Map<string, string[]> {\n const perSource = new Map<string, Set<string>>();\n for (const e of edges) {\n if (!parseSymbolId(e.dstId)) continue;\n let set = perSource.get(e.srcId);\n if (!set) {\n set = new Set();\n perSource.set(e.srcId, set);\n }\n set.add(e.dstId);\n }\n const out = new Map<string, string[]>();\n for (const [src, set] of perSource) out.set(src, [...set].sort());\n return out;\n}\n\nfunction accumulateSymbolPairs(\n symbols: readonly string[],\n counts: Map<string, number>,\n): void {\n for (let i = 0; i < symbols.length; i++) {\n for (let j = i + 1; j < symbols.length; j++) {\n const key = `${symbols[i]!}\\t${symbols[j]!}`;\n counts.set(key, (counts.get(key) ?? 0) + 1);\n }\n }\n}\n\nfunction finalizePairs(\n counts: ReadonlyMap<string, number>,\n minCoImports: number,\n): SymbolCouplingPair[] {\n const out: SymbolCouplingPair[] = [];\n for (const [key, coImports] of counts) {\n if (coImports < minCoImports) continue;\n const [aId, bId] = key.split(\"\\t\") as [string, string];\n const a = parseSymbolId(aId)!;\n const b = parseSymbolId(bId)!;\n out.push({\n aId,\n aFile: a.fileId,\n aName: a.name,\n bId,\n bFile: b.fileId,\n bName: b.name,\n coImports,\n crossFile: a.fileId !== b.fileId,\n });\n }\n return out.sort(comparePairs);\n}\n\nfunction comparePairs(a: SymbolCouplingPair, b: SymbolCouplingPair): number {\n if (b.coImports !== a.coImports) return b.coImports - a.coImports;\n if (a.crossFile !== b.crossFile) return a.crossFile ? -1 : 1;\n if (a.aId !== b.aId) return a.aId < b.aId ? -1 : 1;\n return a.bId < b.bId ? -1 : a.bId > b.bId ? 1 : 0;\n}\n","import type { GraphEdge, GraphNode } from \"../types.js\";\n\n/**\n * Per-package and per-pair structural quality metrics, plus an overall\n * Newman-Girvan modularity Q for the package partition.\n *\n * Operates on a barrel-resolved edge set by default: edges that land on a\n * file with role=\"barrel\" are rewritten to land on the underlying files\n * the barrel re-exports from (transitively). The intent is to measure the\n * real dependency surface, not the re-export plumbing.\n *\n * See C-8 task notes for the design rationale and empirical calibration\n * data from the 2026-05-21 codewatch dogfood.\n */\n\nexport interface PartitionQualityInput {\n /** Logical packages — at minimum needs an id. */\n packages: ReadonlyArray<{ id: string }>;\n /** Package id → list of file ids assigned to that package. */\n fileByPackage: ReadonlyMap<string, ReadonlyArray<string>>;\n /** All file/module/external nodes for the snapshot. Used to identify role=\"barrel\". */\n nodes: readonly GraphNode[];\n /** All edges for the snapshot. */\n edges: readonly GraphEdge[];\n /**\n * When true, edges landing on a barrel file are resolved through its\n * re-export chain to the underlying source files. The cheap implementation\n * fans each barrel import into N synthetic edges (one per re-export\n * target), which over-attributes — a single `import { x } from \"./pkg\"`\n * becomes N edges as if every re-export were used. Default false until\n * a weighted or symbol-tracking version is available.\n */\n resolveBarrels?: boolean;\n}\n\nexport type PackageFlag = \"weak-boundary\";\nexport type PairFlag = \"tight\" | \"moderate\" | \"none\";\nexport type PackageLayer = \"top\" | \"middle\" | \"foundation\";\n\nexport interface PackageStats {\n pkgId: string;\n fileCount: number;\n internalEdges: number;\n outgoingEdges: number;\n incomingEdges: number;\n /** internal / (internal + outgoing) — higher = more self-contained. */\n cohesion: number;\n /** outgoing / (outgoing + incoming) — Martin's I metric at the package level. */\n instability: number;\n /**\n * Abstractness proxy A ∈ [0,1]: share of the package's files with role\n * \"types\" (dedicated type/interface definitions). codewatch has no\n * symbol-level abstract/concrete counts, so this file-role ratio stands in\n * for Martin's A. Enables the instability×abstractness main-sequence plot.\n */\n abstractness: number;\n layer: PackageLayer;\n flags: PackageFlag[];\n}\n\nexport interface PairCoupling {\n from: string;\n to: string;\n edges: number;\n /** edges / files(from) — fraction of from-side files contributing dependencies into `to`. */\n intensity: number;\n flag: PairFlag;\n}\n\nexport interface PartitionQualityResult {\n modularityQ: number;\n totalEdges: number;\n perPackage: PackageStats[];\n pairCoupling: PairCoupling[];\n /** Total raised flags across packages + pairs (excluding \"moderate\"). */\n flagsCount: number;\n}\n\n// Layer classification — calibrated 2026-05-21 against codewatch's\n// own package shape (cli=1.00 top, analyzer/checker/render=0.70-0.80\n// middle, graph=0.20 foundation-leaning, core/profile=0.00 pure\n// foundation). The earlier 0.7 top threshold mis-labeled middle layers.\nconst FOUNDATION_INSTABILITY_MAX = 0.3;\nconst TOP_INSTABILITY_MIN = 0.9;\nconst WEAK_COHESION_MAX = 0.5;\nconst TIGHT_INTENSITY_MIN = 0.6;\nconst MODERATE_INTENSITY_MIN = 0.3;\n\nexport function computePartitionQuality(\n input: PartitionQualityInput,\n): PartitionQualityResult {\n const resolveBarrels = input.resolveBarrels ?? false;\n const pkgByFile = invertBuckets(input.fileByPackage);\n const barrelTargets = resolveBarrels\n ? buildBarrelTargetMap(input.nodes, input.edges)\n : new Map<string, ReadonlyArray<string>>();\n const resolvedPairs = buildResolvedPairs(\n input.edges,\n pkgByFile,\n barrelTargets,\n resolveBarrels,\n );\n const counts = countByPackage(resolvedPairs);\n const totalEdges = resolvedPairs.length;\n const filesByPkg = filesPerPackage(input.fileByPackage);\n\n const abstractByPkg = countAbstractFiles(input.nodes, pkgByFile);\n const perPackage = input.packages.map((p) =>\n buildPackageStats(p.id, counts, filesByPkg, abstractByPkg),\n );\n const pairCoupling = buildPairCoupling(resolvedPairs, filesByPkg);\n const modularityQ = computeModularity(perPackage, totalEdges);\n const flagsCount =\n perPackage.reduce((acc, p) => acc + p.flags.length, 0) +\n pairCoupling.filter((c) => c.flag === \"tight\").length;\n\n return { modularityQ, totalEdges, perPackage, pairCoupling, flagsCount };\n}\n\n/**\n * Invert a package→files bucket map into a file→package lookup, skipping the\n * empty-string \"unassigned\" bucket. Shared by partition-quality and the CLI's\n * arch/wiki package rollups, which all need the same file→package direction.\n */\nexport function invertBuckets(\n fileByPackage: ReadonlyMap<string, ReadonlyArray<string>>,\n): Map<string, string> {\n const out = new Map<string, string>();\n for (const [pkgId, files] of fileByPackage) {\n if (pkgId === \"\") continue;\n for (const f of files) out.set(f, pkgId);\n }\n return out;\n}\n\nfunction filesPerPackage(\n fileByPackage: ReadonlyMap<string, ReadonlyArray<string>>,\n): Map<string, number> {\n const out = new Map<string, number>();\n for (const [pkgId, files] of fileByPackage) {\n out.set(pkgId, files.length);\n }\n return out;\n}\n\n/**\n * For each barrel file, compute its transitive non-barrel re-export targets.\n * Map omits barrels that re-export nothing reachable (or that aren't barrels).\n */\nfunction buildBarrelTargetMap(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n): Map<string, ReadonlyArray<string>> {\n const barrelIds = new Set(\n nodes.filter((n) => n.role === \"barrel\").map((n) => n.id),\n );\n if (barrelIds.size === 0) return new Map();\n const directReExports = new Map<string, string[]>();\n for (const e of edges) {\n if (!barrelIds.has(e.srcId)) continue;\n if (e.kind !== \"re-exports\") continue;\n let list = directReExports.get(e.srcId);\n if (!list) {\n list = [];\n directReExports.set(e.srcId, list);\n }\n list.push(e.dstId);\n }\n\n const resolved = new Map<string, string[]>();\n const resolve = (barrel: string, visiting: Set<string>): string[] => {\n if (resolved.has(barrel)) return resolved.get(barrel)!;\n if (visiting.has(barrel)) return []; // cycle guard\n visiting.add(barrel);\n const out: string[] = [];\n for (const target of directReExports.get(barrel) ?? []) {\n if (barrelIds.has(target)) {\n for (const inner of resolve(target, visiting)) out.push(inner);\n } else {\n out.push(target);\n }\n }\n visiting.delete(barrel);\n resolved.set(barrel, out);\n return out;\n };\n for (const id of barrelIds) resolve(id, new Set());\n return resolved;\n}\n\n/**\n * Project edges into (fromPkg, toPkg) pairs, resolving through barrels and\n * dropping any edge whose source file isn't in a tracked package. Re-export\n * edges themselves are dropped — they're the resolution mechanism, not\n * substantive dependencies.\n */\nfunction buildResolvedPairs(\n edges: readonly GraphEdge[],\n pkgByFile: ReadonlyMap<string, string>,\n barrelTargets: ReadonlyMap<string, ReadonlyArray<string>>,\n resolveBarrels: boolean,\n): Array<{ from: string; to: string }> {\n const out: Array<{ from: string; to: string }> = [];\n for (const e of edges) {\n // When resolving barrels, the re-export edges become the resolution\n // mechanism (followed implicitly via barrelTargets), so we drop them\n // from the analysis edge set. When NOT resolving, they're substantive\n // dependencies on their own.\n if (resolveBarrels && e.kind === \"re-exports\") continue;\n const fromPkg = pkgByFile.get(e.srcId);\n if (!fromPkg) continue;\n const targets = barrelTargets.get(e.dstId) ?? [e.dstId];\n for (const dst of targets) {\n const toPkg = pkgByFile.get(dst);\n if (toPkg) out.push({ from: fromPkg, to: toPkg });\n }\n }\n return out;\n}\n\ninterface PackageCounts {\n internal: number;\n outgoing: number;\n incoming: number;\n}\n\nfunction countByPackage(\n pairs: ReadonlyArray<{ from: string; to: string }>,\n): Map<string, PackageCounts> {\n const out = new Map<string, PackageCounts>();\n const get = (id: string): PackageCounts => {\n let c = out.get(id);\n if (!c) {\n c = { internal: 0, outgoing: 0, incoming: 0 };\n out.set(id, c);\n }\n return c;\n };\n for (const p of pairs) {\n if (p.from === p.to) {\n get(p.from).internal += 1;\n } else {\n get(p.from).outgoing += 1;\n get(p.to).incoming += 1;\n }\n }\n return out;\n}\n\nfunction buildPackageStats(\n pkgId: string,\n counts: ReadonlyMap<string, PackageCounts>,\n filesByPkg: ReadonlyMap<string, number>,\n abstractByPkg: ReadonlyMap<string, number>,\n): PackageStats {\n const c = counts.get(pkgId) ?? { internal: 0, outgoing: 0, incoming: 0 };\n const cohesion = ratioOrZero(c.internal, c.internal + c.outgoing);\n const instability = ratioOrZero(c.outgoing, c.outgoing + c.incoming);\n const fileCount = filesByPkg.get(pkgId) ?? 0;\n const abstractness = ratioOrZero(abstractByPkg.get(pkgId) ?? 0, fileCount);\n const layer = classifyLayer(instability);\n const flags: PackageFlag[] = [];\n if (layer !== \"top\" && cohesion < WEAK_COHESION_MAX && c.internal + c.outgoing > 0) {\n flags.push(\"weak-boundary\");\n }\n return {\n pkgId,\n fileCount,\n internalEdges: c.internal,\n outgoingEdges: c.outgoing,\n incomingEdges: c.incoming,\n cohesion,\n instability,\n abstractness,\n layer,\n flags,\n };\n}\n\n/** Count files with role \"types\" per package — the abstractness numerator. */\nfunction countAbstractFiles(\n nodes: readonly GraphNode[],\n pkgByFile: ReadonlyMap<string, string>,\n): Map<string, number> {\n const out = new Map<string, number>();\n for (const n of nodes) {\n if (n.kind !== \"file\" || n.role !== \"types\") continue;\n const pkg = pkgByFile.get(n.id);\n if (pkg) out.set(pkg, (out.get(pkg) ?? 0) + 1);\n }\n return out;\n}\n\nfunction ratioOrZero(num: number, denom: number): number {\n return denom === 0 ? 0 : num / denom;\n}\n\nfunction classifyLayer(instability: number): PackageLayer {\n if (instability <= FOUNDATION_INSTABILITY_MAX) return \"foundation\";\n if (instability >= TOP_INSTABILITY_MIN) return \"top\";\n return \"middle\";\n}\n\nfunction buildPairCoupling(\n pairs: ReadonlyArray<{ from: string; to: string }>,\n filesByPkg: ReadonlyMap<string, number>,\n): PairCoupling[] {\n const counts = new Map<string, { from: string; to: string; edges: number }>();\n for (const p of pairs) {\n if (p.from === p.to) continue;\n // Collision-safe key: a JSON tuple, not a raw separator that a real\n // package id could contain (a raw NUL also made git treat this file\n // as binary and hid its diffs).\n const key = JSON.stringify([p.from, p.to]);\n const entry = counts.get(key);\n if (entry) entry.edges += 1;\n else counts.set(key, { from: p.from, to: p.to, edges: 1 });\n }\n const out: PairCoupling[] = [];\n for (const { from, to, edges } of counts.values()) {\n const filesFrom = filesByPkg.get(from) ?? 0;\n const intensity = filesFrom === 0 ? 0 : edges / filesFrom;\n const flag = classifyPairIntensity(intensity);\n out.push({ from, to, edges, intensity, flag });\n }\n return out.sort(comparePairs);\n}\n\nfunction classifyPairIntensity(intensity: number): PairFlag {\n if (intensity >= TIGHT_INTENSITY_MIN) return \"tight\";\n if (intensity >= MODERATE_INTENSITY_MIN) return \"moderate\";\n return \"none\";\n}\n\nfunction comparePairs(a: PairCoupling, b: PairCoupling): number {\n if (a.from !== b.from) return a.from < b.from ? -1 : 1;\n return a.to < b.to ? -1 : 1;\n}\n\n/**\n * Newman-Girvan modularity Q against the package partition (undirected\n * approximation: each directed edge contributes 1 to the source's degree\n * and 1 to the target's). For totalEdges=0 returns 0.\n */\nfunction computeModularity(\n perPackage: readonly PackageStats[],\n totalEdges: number,\n): number {\n if (totalEdges === 0) return 0;\n let Q = 0;\n for (const p of perPackage) {\n const e_cc = p.internalEdges / totalEdges;\n const touching = p.internalEdges * 2 + p.outgoingEdges + p.incomingEdges;\n const a_c = touching / (2 * totalEdges);\n Q += e_cc - a_c * a_c;\n }\n return Q;\n}\n","import type { CodeGraphStore } from \"../store.js\";\nimport { computePageRank, type PageRankOptions, type PageRankResult } from \"./pagerank.js\";\nimport { computeRelevance, type RelevanceOptions } from \"./relevance.js\";\nimport {\n computeSymbolConsumers,\n computeSymbolCoupling,\n type ReferenceEdgeLite,\n type SymbolConsumers,\n type SymbolCouplingOptions,\n type SymbolCouplingPair,\n} from \"./symbol-coupling.js\";\n\n/**\n * PageRank over one snapshot's file-level graph (symbol nodes and `references`\n * edges excluded, as codewatch's `graph relevant` reads it). Pass\n * `personalization` to seed the walk toward target node ids.\n */\nexport function snapshotPageRank(\n store: CodeGraphStore,\n snapshotId: number,\n options: PageRankOptions = {},\n): PageRankResult {\n // The store reads rows unordered, so float-tied scores may order differently than in codewatch.\n return computePageRank(store.listNodes(snapshotId), store.listEdges(snapshotId), options);\n}\n\n/** Relevance of every file-level node to `seedIds`, as codewatch's `graph context` computes it. */\nexport function snapshotRelevance(\n store: CodeGraphStore,\n snapshotId: number,\n seedIds: readonly string[],\n options: RelevanceOptions = {},\n): Map<string, number> {\n return computeRelevance(store.listNodes(snapshotId), store.listEdges(snapshotId), seedIds, options);\n}\n\n/** The snapshot's `references` edges: importing file to imported symbol. */\nexport function snapshotReferenceEdges(store: CodeGraphStore, snapshotId: number): ReferenceEdgeLite[] {\n return store\n .listEdges(snapshotId, { includeReferences: true })\n .filter((e) => e.kind === \"references\")\n .map((e) => ({ srcId: e.srcId, dstId: e.dstId }));\n}\n\n/** Per-symbol consumer files for one snapshot. */\nexport function snapshotSymbolConsumers(store: CodeGraphStore, snapshotId: number): SymbolConsumers[] {\n return computeSymbolConsumers(snapshotReferenceEdges(store, snapshotId));\n}\n\n/** Co-import symbol coupling pairs for one snapshot. */\nexport function snapshotSymbolCoupling(\n store: CodeGraphStore,\n snapshotId: number,\n options: SymbolCouplingOptions = {},\n): SymbolCouplingPair[] {\n return computeSymbolCoupling(snapshotReferenceEdges(store, snapshotId), options);\n}\n","import type { CodeGraphStore } from \"./store.js\";\nimport type { MetricAggregate } from \"./store-reads.js\";\nimport type { GraphEdge, GraphMetric, GraphNode } from \"./types.js\";\n\n/**\n * The free-function reading surface named in the package API. Each delegates to\n * the store's method of the same name, so a caller that only reads a snapshot\n * never has to hold on to the store's shape.\n */\nexport function listNodes(\n store: CodeGraphStore,\n snapshotId: number,\n opts?: { includeSymbols?: boolean },\n): GraphNode[] {\n return store.listNodes(snapshotId, opts);\n}\n\nexport function listEdges(\n store: CodeGraphStore,\n snapshotId: number,\n opts?: { includeReferences?: boolean },\n): GraphEdge[] {\n return store.listEdges(snapshotId, opts);\n}\n\nexport function listMetrics(store: CodeGraphStore, snapshotId: number): GraphMetric[] {\n return store.listMetrics(snapshotId);\n}\n\nexport function listMetricsForNode(store: CodeGraphStore, snapshotId: number, nodeId: string): GraphMetric[] {\n return store.listMetricsForNode(snapshotId, nodeId);\n}\n\nexport function listEdgesTouching(\n store: CodeGraphStore,\n snapshotId: number,\n nodeId: string,\n opts?: { includeReferences?: boolean },\n): GraphEdge[] {\n return store.listEdgesTouching(snapshotId, nodeId, opts);\n}\n\nexport function aggregateMetrics(\n store: CodeGraphStore,\n snapshotId: number,\n opts?: { name?: string },\n): MetricAggregate[] {\n return store.aggregateMetrics(snapshotId, opts);\n}\n","import type { NodeKind } from \"../types.js\";\nimport type { MetricDescriptor } from \"./types.js\";\n\nconst FILE: readonly NodeKind[] = [\"file\"];\nconst SYMBOL: readonly NodeKind[] = [\"symbol\"];\nconst STRUCTURAL: readonly NodeKind[] = [\"file\", \"module\", \"external\"];\n\n/** Degree metrics from `metrics.ts`, recomputed over the whole assembled graph on every index. */\nconst DEGREE: readonly MetricDescriptor[] = [\n {\n name: \"fan_in\", unit: \"count\", appliesTo: STRUCTURAL, rollup: \"none\", direction: \"neutral\",\n absent: \"zero\", source: \"degree\",\n description: \"Import and re-export edges into the node. Summing over a group would count its internal edges.\",\n },\n {\n name: \"fan_out\", unit: \"count\", appliesTo: STRUCTURAL, rollup: \"none\", direction: \"higher-worse\",\n absent: \"zero\", source: \"degree\",\n description: \"Import and re-export edges out of the node. Summing over a group would count its internal edges.\",\n },\n {\n name: \"instability\", unit: \"ratio\", appliesTo: STRUCTURAL, rollup: \"none\", direction: \"neutral\",\n absent: \"exclude\", source: \"degree\",\n description: \"fan_out / (fan_in + fan_out); written only when the node has an import edge.\",\n },\n {\n name: \"utilization\", unit: \"count\", appliesTo: [...STRUCTURAL, \"symbol\"], rollup: \"none\", direction: \"neutral\",\n absent: \"zero\", source: \"degree\",\n description: \"Inbound edges weighted by reference count over the barrel-resolved graph: how heavily a node is used.\",\n },\n];\n\n/** Pure functions of one file's bytes (`source-metrics.ts`, `lcom.ts`), carried forward under reuse. */\nconst SOURCE: readonly MetricDescriptor[] = [\n {\n name: \"loc\", unit: \"lines\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"source-metrics\", description: \"Non-blank lines in the file.\",\n },\n {\n name: \"function_count\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"neutral\",\n absent: \"zero\", source: \"source-metrics\", description: \"Functions, methods, and arrow functions declared in the file.\",\n },\n {\n name: \"cyclomatic_max\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\", description: \"Highest cyclomatic complexity of any function in the file.\",\n },\n {\n name: \"cyclomatic_sum\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"source-metrics\", description: \"Cyclomatic complexity summed over the file's functions.\",\n },\n {\n name: \"cognitive_max\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\", description: \"Highest cognitive complexity of any function in the file.\",\n },\n {\n name: \"cognitive_sum\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"source-metrics\", description: \"Cognitive complexity summed over the file's functions.\",\n },\n {\n name: \"max_nesting_depth\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\", description: \"Deepest block nesting inside any function in the file.\",\n },\n {\n name: \"symbol_cognitive\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Cognitive complexity of the function a symbol names; the max when several functions share the name.\",\n },\n {\n name: \"symbol_cyclomatic\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Cyclomatic complexity of the function a symbol names; the max when several functions share the name.\",\n },\n {\n name: \"symbol_loc\", unit: \"lines\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Lines spanned by the function a symbol names, signature included; the max when several share the name.\",\n },\n {\n name: \"symbol_max_nesting\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Deepest block nesting inside the function a symbol names; the max when several share the name.\",\n },\n {\n name: \"symbol_comment_lines\", unit: \"lines\", appliesTo: SYMBOL, rollup: \"max\", direction: \"neutral\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Rows holding a comment inside the function a symbol names, the docstring excluded; the max when several share the name.\",\n },\n {\n name: \"symbol_docstring_lines\", unit: \"lines\", appliesTo: SYMBOL, rollup: \"max\", direction: \"neutral\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Rows of the function's docstring: the Python docstring, or the JSDoc block attached to a TypeScript declaration.\",\n },\n {\n name: \"symbol_body_lines\", unit: \"lines\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Non-blank rows of the function's body that hold code, comments and the docstring excluded.\",\n },\n {\n name: \"symbol_comment_ratio\", unit: \"ratio\", appliesTo: SYMBOL, rollup: \"max\", direction: \"neutral\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"symbol_comment_lines / max(symbol_body_lines, 1). High values suggest narration; zero is not a defect.\",\n },\n {\n name: \"symbol_narrating_comments\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Comments in the body whose words overlap the next statement's identifiers by 2 tokens or half the comment. A candidate signal.\",\n },\n {\n name: \"symbol_pass_through\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"1 when the function's body is one call forwarding every parameter, in order, as a bare argument; else 0.\",\n },\n {\n name: \"symbol_caller_count\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"neutral\",\n absent: \"exclude\", source: \"call-graph\",\n description: \"Distinct symbols, or files at module level, with a resolved call to this function, method or class. Unresolved calls are not counted.\",\n },\n {\n name: \"symbol_single_caller_helper\", unit: \"count\", appliesTo: SYMBOL, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"call-graph\",\n description: \"1 when a non-exported symbol has exactly one resolved caller and that caller is a symbol; else 0.\",\n },\n {\n name: \"symbol_constant_params\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"call-graph\",\n description: \"Parameters that every one of at least 2 resolved call sites passes the same literal, or never passes. Rest and keyword-splat parameters are ignored.\",\n },\n {\n name: \"except_count\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"neutral\",\n absent: \"zero\", source: \"exception-handling\", description: \"Python except clauses and TypeScript catch clauses in the file.\",\n },\n {\n name: \"except_density\", unit: \"per100loc\", appliesTo: FILE, rollup: \"none\", direction: \"higher-worse\",\n absent: \"zero\", source: \"exception-handling\", description: \"except_count per 100 non-blank lines. Recompute from the sums for a group.\",\n },\n {\n name: \"swallowed_except\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"exception-handling\",\n description: \"Handlers whose body is empty, pass, ..., continue, a bare or empty return, or a single logging call. Exempts Python's `except ImportError`/`ModuleNotFoundError` (alone or paired), the standard optional-dependency idiom.\",\n },\n {\n name: \"class_count\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"neutral\",\n absent: \"zero\", source: \"lcom\", description: \"Classes declared in the file; written only when there is one.\",\n },\n {\n name: \"lcom4_max\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"lcom\", description: \"Highest LCOM4 of any class in the file; above 1 means the class could split.\",\n },\n];\n\n/** Sparse per-file smells: a row only when the count clears the writer's floor. */\nconst SMELLS: readonly MetricDescriptor[] = [\n {\n name: \"unreachable_statements\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"dead-code\", description: \"Statements after an unconditional return, throw, break, or continue. TypeScript only.\",\n },\n {\n name: \"unused_locals\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"dead-code\", description: \"Local bindings never read. TypeScript only.\",\n },\n {\n name: \"unused_params\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"dead-code\", description: \"Trailing parameters never read. TypeScript only.\",\n },\n {\n name: \"loop_depth\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"zero\", source: \"growth-risk\", description: \"Deepest lexical loop nesting; written at 2 or more.\",\n },\n {\n name: \"recursive_functions\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"growth-risk\", description: \"Functions that call themselves by name. TypeScript only.\",\n },\n {\n name: \"search_in_loop\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"growth-risk\", description: \"Linear searches such as .includes or .find inside a loop. TypeScript only.\",\n },\n];\n\n/** Git-history metrics from `history-metrics.ts`; `{w}` is a window such as `30d` or `lifetime`. */\nconst HISTORY: readonly MetricDescriptor[] = [\n {\n name: \"churn_{w}\", unit: \"lines\", appliesTo: FILE, rollup: \"sum\", direction: \"neutral\",\n absent: \"zero\", source: \"history\", windowed: true, description: \"Lines added plus deleted in the {w} window.\",\n },\n {\n name: \"churn_{w}_commits\", unit: \"count\", appliesTo: FILE, rollup: \"none\", direction: \"neutral\",\n absent: \"zero\", source: \"history\", windowed: true,\n description: \"Commits touching the file in the {w} window. A group's distinct commits are not the sum.\",\n },\n {\n name: \"churn_{w}_authors\", unit: \"count\", appliesTo: FILE, rollup: \"none\", direction: \"neutral\",\n absent: \"zero\", source: \"history\", windowed: true,\n description: \"Distinct authors of the file's commits in the {w} window. Not additive.\",\n },\n {\n name: \"recency_{w}\", unit: \"ratio\", appliesTo: FILE, rollup: \"none\", direction: \"neutral\",\n absent: \"exclude\", source: \"history\", windowed: true,\n description: \"min(1, file age / window) for a file that churned in the {w} window; 1 for lifetime. A hotspot discount.\",\n },\n {\n name: \"file_age_days\", unit: \"days\", appliesTo: FILE, rollup: \"max\", direction: \"neutral\",\n absent: \"exclude\", source: \"history\", description: \"Days since the file first appeared in git history.\",\n },\n {\n name: \"bus_factor_{w}\", unit: \"count\", appliesTo: FILE, rollup: \"none\", direction: \"lower-worse\",\n absent: \"exclude\", source: \"history\", windowed: true,\n description: \"Fewest authors covering half the file's churn in the {w} window.\",\n },\n {\n name: \"top_author_share_{w}\", unit: \"ratio\", appliesTo: FILE, rollup: \"none\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"history\", windowed: true,\n description: \"Share of the file's churn in the {w} window written by its top author.\",\n },\n];\n\n/** Test linking (`test-linker.ts`) and the Istanbul overlay (`coverage.ts`), keyed on source nodes. */\nconst TESTS: readonly MetricDescriptor[] = [\n {\n name: \"linked_test_count\", unit: \"count\", appliesTo: FILE, rollup: \"none\", direction: \"lower-worse\",\n absent: \"zero\", source: \"test-linker\",\n description: \"Test files linked to this source. One test can link to several sources, so it does not sum.\",\n },\n {\n name: \"test_bus_factor_{w}\", unit: \"count\", appliesTo: FILE, rollup: \"none\", direction: \"lower-worse\",\n absent: \"exclude\", source: \"test-linker\", windowed: true,\n description: \"Bus factor of the churn on this source's linked tests in the {w} window.\",\n },\n {\n name: \"test_top_author_share_{w}\", unit: \"ratio\", appliesTo: FILE, rollup: \"none\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"test-linker\", windowed: true,\n description: \"Top author's share of the churn on this source's linked tests in the {w} window.\",\n },\n {\n name: \"coverage_pct\", unit: \"percent\", appliesTo: [\"file\", \"symbol\"], rollup: \"none\", direction: \"lower-worse\",\n absent: \"exclude\", source: \"coverage\",\n description: \"Functions covered over functions total, from an ingested Istanbul report. Never written by the indexer.\",\n },\n];\n\n/** Every metric name code-graph writes, with windowed names as `{w}` templates. */\nexport const METRIC_CATALOGUE: readonly MetricDescriptor[] = [...DEGREE, ...SOURCE, ...SMELLS, ...HISTORY, ...TESTS];\n","import { METRIC_CATALOGUE } from \"./entries.js\";\nimport type { MetricDescriptor } from \"./types.js\";\n\nconst WINDOW_TOKEN = \"{w}\";\n/** Mirrors `windowSuffix` in history-recency.ts, which this module cannot import and stay free of Node. */\nconst WINDOW_PATTERN = \"(\\\\d+d|lifetime)\";\n\ninterface WindowedMatcher {\n pattern: RegExp;\n template: MetricDescriptor;\n}\n\nconst BY_NAME = new Map(METRIC_CATALOGUE.filter((d) => !d.windowed).map((d) => [d.name, d]));\n\nconst WINDOWED: readonly WindowedMatcher[] = METRIC_CATALOGUE.filter((d) => d.windowed).map((template) => ({\n pattern: new RegExp(`^${template.name.replace(WINDOW_TOKEN, WINDOW_PATTERN)}$`),\n template,\n}));\n\nfunction resolveWindow(template: MetricDescriptor, window: string): MetricDescriptor {\n const resolved: MetricDescriptor = {\n ...template,\n name: template.name.replace(WINDOW_TOKEN, window),\n description: template.description.replace(WINDOW_TOKEN, window),\n window,\n };\n delete resolved.windowed;\n return resolved;\n}\n\n/** The descriptor for a stored metric name, resolving windowed names such as `churn_90d`; null when uncatalogued. */\nexport function describeMetric(name: string): MetricDescriptor | null {\n const exact = BY_NAME.get(name);\n if (exact) return exact;\n for (const { pattern, template } of WINDOWED) {\n const match = pattern.exec(name);\n if (match) return resolveWindow(template, match[1]!);\n }\n return null;\n}\n\n/** Descriptors for a set of stored names, in the order given; uncatalogued names are returned separately. */\nexport function describeMetrics(names: Iterable<string>): { described: MetricDescriptor[]; unknown: string[] } {\n const described: MetricDescriptor[] = [];\n const unknown: string[] = [];\n for (const name of new Set(names)) {\n const descriptor = describeMetric(name);\n if (descriptor) described.push(descriptor);\n else unknown.push(name);\n }\n return { described, unknown };\n}\n","import type { CodeGraphStore } from \"../store.js\";\nimport type { GraphEdge, GraphMetric, GraphNode } from \"../types.js\";\n\n/** The three whole-snapshot reads rule evaluation needs; any store with them can be checked. */\nexport type RuleStore = Pick<CodeGraphStore, \"listNodes\" | \"listEdges\" | \"listMetrics\">;\n\nexport interface RuleContext {\n nodes: readonly GraphNode[];\n /** Kept apart from `nodes` so only rules that ask for `kind: \"symbol\"` evaluate them. */\n symbolNodes: readonly GraphNode[];\n nodesById: Map<string, GraphNode>;\n metricsByNode: Map<string, Map<string, number>>;\n edges: readonly GraphEdge[];\n}\n\n/** The snapshot's file-level graph (no references edges), its symbol layer, and its non-null metrics. */\nexport function buildRuleContext(store: RuleStore, snapshotId: number): RuleContext {\n const all = store.listNodes(snapshotId, { includeSymbols: true });\n const nodes = all.filter((n) => n.kind !== \"symbol\");\n const symbolNodes = all.filter((n) => n.kind === \"symbol\");\n const edges = store.listEdges(snapshotId);\n const nodesById = new Map<string, GraphNode>();\n for (const n of nodes) nodesById.set(n.id, n);\n return { nodes, symbolNodes, nodesById, metricsByNode: indexMetrics(store.listMetrics(snapshotId)), edges };\n}\n\nfunction indexMetrics(metrics: readonly GraphMetric[]): Map<string, Map<string, number>> {\n const metricsByNode = new Map<string, Map<string, number>>();\n for (const m of metrics) {\n if (m.value === null) continue;\n let inner = metricsByNode.get(m.nodeId);\n if (!inner) {\n inner = new Map();\n metricsByNode.set(m.nodeId, inner);\n }\n inner.set(m.name, m.value);\n }\n return metricsByNode;\n}\n","/** Glob when the pattern has a `*` (`**` crosses directories, `*` stays in a segment); otherwise a case-sensitive substring. */\nexport function patternToRegex(pattern: string): RegExp {\n if (!pattern.includes(\"*\")) {\n return new RegExp(escapeRegex(pattern));\n }\n let out = \"\";\n for (let i = 0; i < pattern.length; i++) {\n const c = pattern[i]!;\n if (c === \"*\" && pattern[i + 1] === \"*\") {\n out += \".*\";\n i++;\n } else if (c === \"*\") {\n out += \"[^/]*\";\n } else {\n out += escapeRegex(c);\n }\n }\n return new RegExp(`^${out}$`);\n}\n\nexport function compilePatterns(patterns: readonly string[] | undefined): RegExp[] {\n if (!patterns) return [];\n return patterns.map(patternToRegex);\n}\n\nexport function matchesAny(value: string, patterns: readonly RegExp[]): boolean {\n for (const rx of patterns) {\n if (rx.test(value)) return true;\n }\n return false;\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.+?(){}|^$\\\\[\\]]/g, \"\\\\$&\");\n}\n","import type { GraphEdge } from \"../types.js\";\nimport type { CheckRule, Severity } from \"./types.js\";\n\nexport function severityOf(rule: CheckRule): Severity {\n return rule.severity ?? \"error\";\n}\n\nexport function formatNumber(n: number): string {\n if (Number.isInteger(n)) return String(n);\n return n.toFixed(3).replace(/\\.?0+$/, \"\");\n}\n\nexport function isImportEdge(edge: GraphEdge): boolean {\n return edge.kind === \"imports\" || edge.kind === \"re-exports\";\n}\n\n/** Maps an id to the longest prefix it sits under, so a nested package wins over its parent. */\nexport function longestPrefixMatcher(prefixes: readonly string[]): (id: string) => string | null {\n const byLength = [...prefixes].sort((a, b) => b.length - a.length);\n return (id) => {\n for (const p of byLength) {\n if (id === p || id.startsWith(`${p}/`)) return p;\n }\n return null;\n };\n}\n","import type { GraphEdge } from \"../types.js\";\nimport type { RuleContext } from \"./context.js\";\nimport { compilePatterns, matchesAny } from \"./patterns.js\";\nimport { isImportEdge, longestPrefixMatcher, severityOf } from \"./rule-helpers.js\";\nimport type {\n CheckViolation,\n ForbidImportRule,\n LayeredDepsRule,\n NoInternalOnlyBarrelsRule,\n} from \"./types.js\";\n\nfunction layerIndex(layers: readonly string[][]): Map<string, number> {\n const packageLayer = new Map<string, number>();\n for (let i = 0; i < layers.length; i++) {\n for (const pkg of layers[i]!) packageLayer.set(pkg, i);\n }\n return packageLayer;\n}\n\n/** Layer strings are path prefixes such as `packages/cli`; an edge may only point to its own layer or a lower one. */\nexport function runLayeredDepsRule(rule: LayeredDepsRule, ctx: RuleContext): CheckViolation[] {\n const packageLayer = layerIndex(rule.layers);\n const packageOf = longestPrefixMatcher([...packageLayer.keys()]);\n const out: CheckViolation[] = [];\n for (const edge of ctx.edges) {\n if (!isImportEdge(edge)) continue;\n const srcPkg = packageOf(edge.srcId);\n const dstPkg = packageOf(edge.dstId);\n if (srcPkg === null || dstPkg === null) continue;\n const srcLayer = packageLayer.get(srcPkg)!;\n const dstLayer = packageLayer.get(dstPkg)!;\n if (srcLayer >= dstLayer) continue;\n out.push({\n ruleId: rule.id,\n severity: severityOf(rule),\n nodeId: edge.srcId,\n destinationId: edge.dstId,\n message: `${srcPkg} (layer ${srcLayer}) imports ${dstPkg} (layer ${dstLayer})`,\n });\n }\n return out;\n}\n\nexport function runForbidImportRule(rule: ForbidImportRule, ctx: RuleContext): CheckViolation[] {\n const fromRx = compilePatterns([rule.from]);\n const toRx = compilePatterns([rule.to]);\n const out: CheckViolation[] = [];\n for (const edge of ctx.edges) {\n if (!isImportEdge(edge)) continue;\n if (!matchesAny(edge.srcId, fromRx)) continue;\n if (!matchesAny(edge.dstId, toRx)) continue;\n out.push({\n ruleId: rule.id,\n severity: severityOf(rule),\n nodeId: edge.srcId,\n destinationId: edge.dstId,\n message: `${edge.srcId} imports ${edge.dstId} (forbidden: ${rule.from} → ${rule.to})`,\n });\n }\n return out;\n}\n\nfunction importersByDestination(edges: readonly GraphEdge[]): Map<string, string[]> {\n const importersByDst = new Map<string, string[]>();\n for (const edge of edges) {\n if (!isImportEdge(edge)) continue;\n let list = importersByDst.get(edge.dstId);\n if (!list) {\n list = [];\n importersByDst.set(edge.dstId, list);\n }\n list.push(edge.srcId);\n }\n return importersByDst;\n}\n\nexport function runNoInternalOnlyBarrelsRule(\n rule: NoInternalOnlyBarrelsRule,\n ctx: RuleContext,\n): CheckViolation[] {\n const packageOf = longestPrefixMatcher(rule.packageRoots);\n const excluders = compilePatterns(rule.exclude);\n const importersByDst = importersByDestination(ctx.edges);\n const out: CheckViolation[] = [];\n for (const node of ctx.nodes) {\n if (node.kind !== \"file\") continue;\n if (node.role !== \"barrel\") continue;\n if (matchesAny(node.id, excluders)) continue;\n const barrelPkg = packageOf(node.id);\n if (barrelPkg === null) continue;\n const importers = importersByDst.get(node.id) ?? [];\n const externalCount = importers.reduce((n, src) => (packageOf(src) !== barrelPkg ? n + 1 : n), 0);\n if (externalCount > 0) continue;\n out.push({\n ruleId: rule.id,\n severity: severityOf(rule),\n nodeId: node.id,\n message: barrelMessage(barrelPkg, importers.length),\n });\n }\n return out;\n}\n\nfunction barrelMessage(barrelPkg: string, importerCount: number): string {\n return importerCount === 0\n ? `barrel in package \"${barrelPkg}\" has no importers`\n : `barrel in package \"${barrelPkg}\" has ${importerCount} internal importer(s) but zero external`;\n}\n","import type { GraphNode } from \"../types.js\";\nimport type { CheckViolation } from \"./types.js\";\n\nexport const CODE_GRAPH_TOOL = \"code-graph\";\n\nexport type ViolationLocation = Pick<CheckViolation, \"path\" | \"lineStart\" | \"lineEnd\" | \"symbol\">;\n\n/** Where a node lives in the source: a symbol points at its parent file and its own line span. */\nexport function locateNode(node: GraphNode): ViolationLocation {\n if (node.kind !== \"symbol\") return { path: node.id };\n const location: ViolationLocation = { path: node.parentId ?? node.id, symbol: node.name };\n const startLine = node.attrs?.startLine;\n const endLine = node.attrs?.endLine;\n if (typeof startLine === \"number\") location.lineStart = startLine;\n if (typeof endLine === \"number\") location.lineEnd = endLine;\n return location;\n}\n","import type { GraphNode } from \"../types.js\";\nimport type { RuleContext } from \"./context.js\";\nimport { formatNumber, severityOf } from \"./rule-helpers.js\";\nimport type { CheckViolation, MetricOutlierRule } from \"./types.js\";\nimport { CODE_GRAPH_TOOL, locateNode } from \"./violation-location.js\";\n\nexport const DEFAULT_OUTLIER_MIN_SAMPLE = 20;\n\n/**\n * A threshold drawn from the snapshot itself rather than fixed in the rule, so\n * one rule reads the same across repositories of different house styles. Below\n * `minSample` carriers the percentile means little, so the rule stays silent.\n */\nexport function runMetricOutlierRule(rule: MetricOutlierRule, ctx: RuleContext): CheckViolation[] {\n const pool = rule.kind === \"symbol\" ? ctx.symbolNodes : ctx.nodes;\n const carriers: { node: GraphNode; value: number }[] = [];\n for (const node of pool) {\n if (node.kind !== rule.kind) continue;\n const value = ctx.metricsByNode.get(node.id)?.get(rule.metric);\n if (value !== undefined) carriers.push({ node, value });\n }\n const ranked = rule.rankNonZero ? carriers.filter((c) => c.value > 0) : carriers;\n if (ranked.length < (rule.minSample ?? DEFAULT_OUTLIER_MIN_SAMPLE)) return [];\n const threshold = percentileOf(ranked.map((c) => c.value), rule.percentile);\n return ranked\n .filter((c) => c.value > threshold && (rule.floor === undefined || c.value > rule.floor))\n .map((c) => toViolation(rule, c.node, c.value, threshold));\n}\n\n/** Linear interpolation between closest ranks, the definition numpy and spreadsheets use by default. */\nexport function percentileOf(values: readonly number[], percentile: number): number {\n const sorted = [...values].sort((a, b) => a - b);\n const rank = (percentile / 100) * (sorted.length - 1);\n const lower = Math.floor(rank);\n const upper = Math.min(lower + 1, sorted.length - 1);\n return sorted[lower]! + (sorted[upper]! - sorted[lower]!) * (rank - lower);\n}\n\nfunction toViolation(rule: MetricOutlierRule, node: GraphNode, value: number, threshold: number): CheckViolation {\n const floorSuffix = rule.floor === undefined ? \"\" : `, floor ${formatNumber(rule.floor)}`;\n const bound = `p${formatNumber(rule.percentile)} ${formatNumber(threshold)}${floorSuffix}`;\n return {\n ruleId: rule.id,\n severity: severityOf(rule),\n nodeId: node.id,\n metric: rule.metric,\n value,\n threshold,\n message: `${rule.metric}=${formatNumber(value)} > ${bound}`,\n ...locateNode(node),\n evidence: `${rule.metric}=${formatNumber(value)} (${bound})`,\n tool: CODE_GRAPH_TOOL,\n };\n}\n","import type { GraphNode, NodeKind, NodeRole } from \"../types.js\";\nimport type { RuleContext } from \"./context.js\";\nimport { compilePatterns, matchesAny } from \"./patterns.js\";\nimport { formatNumber, severityOf } from \"./rule-helpers.js\";\nimport type {\n CheckViolation,\n MetricMaxRule,\n MetricMinRule,\n MetricProductMaxRule,\n} from \"./types.js\";\nimport { CODE_GRAPH_TOOL, locateNode } from \"./violation-location.js\";\n\ntype MetricRule = MetricMaxRule | MetricMinRule | MetricProductMaxRule;\n\ninterface NodeFilter {\n kind?: NodeKind;\n excluders: RegExp[];\n excludedRoles: Set<NodeRole>;\n}\n\nfunction nodeFilter(rule: MetricRule): NodeFilter {\n return {\n kind: rule.kind,\n excluders: compilePatterns(rule.exclude),\n excludedRoles: new Set(rule.excludeRoles ?? []),\n };\n}\n\nfunction passesFilter(node: GraphNode, filter: NodeFilter): boolean {\n if (filter.kind && node.kind !== filter.kind) return false;\n if (matchesAny(node.id, filter.excluders)) return false;\n if (node.role && filter.excludedRoles.has(node.role)) return false;\n return true;\n}\n\n/** Symbol nodes only when the rule asks for them, so file rules and their baselines stay as they were. */\nfunction candidateNodes(rule: MetricRule, ctx: RuleContext): GraphNode[] {\n const filter = nodeFilter(rule);\n const pool = rule.kind === \"symbol\" ? ctx.symbolNodes : ctx.nodes;\n return pool.filter((node) => passesFilter(node, filter));\n}\n\ninterface Breach {\n node: GraphNode;\n metric: string;\n value: number;\n threshold: number;\n message: string;\n evidence: string;\n}\n\nfunction toViolation(rule: MetricRule, breach: Breach): CheckViolation {\n return {\n ruleId: rule.id,\n severity: severityOf(rule),\n nodeId: breach.node.id,\n metric: breach.metric,\n value: breach.value,\n threshold: breach.threshold,\n message: breach.message,\n ...locateNode(breach.node),\n evidence: breach.evidence,\n tool: CODE_GRAPH_TOOL,\n };\n}\n\nfunction thresholdBreach(node: GraphNode, metric: string, value: number, bound: \"max\" | \"min\", threshold: number): Breach {\n const op = bound === \"max\" ? \">\" : \"<\";\n return {\n node,\n metric,\n value,\n threshold,\n message: `${metric}=${formatNumber(value)} ${op} ${formatNumber(threshold)}`,\n evidence: `${metric}=${formatNumber(value)} (${bound} ${formatNumber(threshold)})`,\n };\n}\n\nexport function runMetricMaxRule(rule: MetricMaxRule, ctx: RuleContext): CheckViolation[] {\n const out: CheckViolation[] = [];\n for (const node of candidateNodes(rule, ctx)) {\n const value = ctx.metricsByNode.get(node.id)?.get(rule.metric);\n if (value === undefined || value <= rule.max) continue;\n out.push(toViolation(rule, thresholdBreach(node, rule.metric, value, \"max\", rule.max)));\n }\n return out;\n}\n\nexport function runMetricMinRule(rule: MetricMinRule, ctx: RuleContext): CheckViolation[] {\n const out: CheckViolation[] = [];\n for (const node of candidateNodes(rule, ctx)) {\n const value = ctx.metricsByNode.get(node.id)?.get(rule.metric);\n if (value === undefined || value >= rule.min) continue;\n out.push(toViolation(rule, thresholdBreach(node, rule.metric, value, \"min\", rule.min)));\n }\n return out;\n}\n\nexport function runMetricProductMaxRule(rule: MetricProductMaxRule, ctx: RuleContext): CheckViolation[] {\n const out: CheckViolation[] = [];\n for (const node of candidateNodes(rule, ctx)) {\n const inner = ctx.metricsByNode.get(node.id);\n if (!inner) continue;\n const components = collectComponents(rule.metrics, inner);\n if (!components) continue;\n const product = components.reduce((a, b) => a * b, 1);\n if (product <= rule.max) continue;\n out.push(toViolation(rule, productBreach(rule, node, components, product)));\n }\n return out;\n}\n\nfunction productBreach(\n rule: MetricProductMaxRule,\n node: GraphNode,\n components: readonly number[],\n product: number,\n): Breach {\n const detail = rule.metrics.map((m, i) => `${m}=${formatNumber(components[i]!)}`).join(\" * \");\n return {\n node,\n metric: rule.metrics.join(\" * \"),\n value: product,\n threshold: rule.max,\n message: `${detail} = ${formatNumber(product)} > ${formatNumber(rule.max)}`,\n evidence: `${detail} = ${formatNumber(product)} (max ${formatNumber(rule.max)})`,\n };\n}\n\nfunction collectComponents(\n metrics: readonly string[],\n values: ReadonlyMap<string, number>,\n): number[] | null {\n const out: number[] = [];\n for (const m of metrics) {\n const v = values.get(m);\n if (v === undefined) return null;\n out.push(v);\n }\n return out;\n}\n","import type { RuleContext } from \"./context.js\";\nimport { runForbidImportRule, runLayeredDepsRule, runNoInternalOnlyBarrelsRule } from \"./import-rules.js\";\nimport { runMetricOutlierRule } from \"./outlier-rule.js\";\nimport { runMetricMaxRule, runMetricMinRule, runMetricProductMaxRule } from \"./metric-rules.js\";\nimport type { CheckRule, CheckViolation } from \"./types.js\";\n\nexport function runRule(rule: CheckRule, ctx: RuleContext): CheckViolation[] {\n switch (rule.type) {\n case \"metric-max\":\n return runMetricMaxRule(rule, ctx);\n case \"metric-min\":\n return runMetricMinRule(rule, ctx);\n case \"metric-product-max\":\n return runMetricProductMaxRule(rule, ctx);\n case \"metric-outlier\":\n return runMetricOutlierRule(rule, ctx);\n case \"forbid-import\":\n return runForbidImportRule(rule, ctx);\n case \"layered-deps\":\n return runLayeredDepsRule(rule, ctx);\n case \"no-internal-only-barrels\":\n return runNoInternalOnlyBarrelsRule(rule, ctx);\n }\n}\n","import { aliasChain } from \"../identity/store-identity.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { buildRuleContext, type RuleStore } from \"./context.js\";\nimport { runRule } from \"./rules.js\";\nimport type { CheckResult, CheckRule, CheckViolation } from \"./types.js\";\n\nexport interface RunChecksOptions {\n snapshotId: number;\n rules: readonly CheckRule[];\n baselineSnapshotId?: number;\n}\n\nexport function runChecks(store: CodeGraphStore, options: RunChecksOptions): CheckResult {\n const ctx = buildRuleContext(store, options.snapshotId);\n const violations: CheckViolation[] = [];\n for (const rule of options.rules) {\n violations.push(...runRule(rule, ctx));\n }\n if (options.baselineSnapshotId) {\n const baselineKeys = collectBaselineKeys(store, options.baselineSnapshotId, options.snapshotId, options.rules);\n for (const v of violations) {\n if (baselineKeys.has(violationKey(v))) v.isCarryover = true;\n }\n }\n const counts = countByOriginAndSeverity(violations);\n return {\n snapshotId: options.snapshotId,\n baselineSnapshotId: options.baselineSnapshotId,\n rulesEvaluated: options.rules.length,\n nodesEvaluated: ctx.nodes.length,\n violations,\n ...counts,\n passed: counts.newErrors === 0,\n };\n}\n\n/** Every rule's violations in one snapshot with no baseline; needs only the three whole-snapshot reads. */\nexport function snapshotViolations(store: RuleStore, snapshotId: number, rules: readonly CheckRule[]): CheckViolation[] {\n const ctx = buildRuleContext(store, snapshotId);\n return rules.flatMap((rule) => runRule(rule, ctx));\n}\n\n/** Baseline violation keys in the checked snapshot's id space, so a moved file's violations carry over. */\nfunction collectBaselineKeys(\n store: CodeGraphStore,\n baselineSnapshotId: number,\n snapshotId: number,\n rules: readonly CheckRule[],\n): Set<string> {\n const ctx = buildRuleContext(store, baselineSnapshotId);\n const chain = aliasChain(store, baselineSnapshotId, snapshotId);\n const keys = new Set<string>();\n for (const rule of rules) {\n for (const v of runRule(rule, ctx)) keys.add(rebasedViolationKey(v, chain.resolve));\n }\n return keys;\n}\n\n/** Identity of a violation across snapshots: severity, value and message may change, the key does not. */\nexport function violationKey(v: CheckViolation): string {\n return v.destinationId ? `${v.ruleId}|${v.nodeId}|${v.destinationId}` : `${v.ruleId}|${v.nodeId}`;\n}\n\n/** {@link violationKey} with both node ids carried into another snapshot's id space; unmoved ids key as before. */\nexport function rebasedViolationKey(v: CheckViolation, resolve: (id: string) => string): string {\n const destinationId = v.destinationId ? resolve(v.destinationId) : v.destinationId;\n return violationKey({ ...v, nodeId: resolve(v.nodeId), destinationId });\n}\n\ninterface Counts {\n newErrors: number;\n newWarnings: number;\n carryoverErrors: number;\n carryoverWarnings: number;\n}\n\nfunction countByOriginAndSeverity(violations: readonly CheckViolation[]): Counts {\n const counts: Counts = { newErrors: 0, newWarnings: 0, carryoverErrors: 0, carryoverWarnings: 0 };\n for (const v of violations) {\n const isError = v.severity === \"error\";\n if (v.isCarryover) {\n if (isError) counts.carryoverErrors++;\n else counts.carryoverWarnings++;\n } else {\n if (isError) counts.newErrors++;\n else counts.newWarnings++;\n }\n }\n return counts;\n}\n","import type { CheckResult, CheckViolation, Severity } from \"./types.js\";\nimport { CODE_GRAPH_TOOL } from \"./violation-location.js\";\n\n/** One tool-neutral audit finding; every finding cites a path so a citation checker can verify it. */\nexport interface Finding {\n id: string;\n path: string;\n lineStart?: number;\n lineEnd?: number;\n symbol?: string;\n signal: string;\n value?: number;\n baseline?: number;\n threshold?: number;\n severity: Severity;\n evidence?: string;\n tool: string;\n}\n\n/** A diagnostic from an outside linter, shaped structurally so no linter package is imported. */\nexport interface ExternalDiagnostic {\n tool: string;\n rule: string;\n file: string;\n line: number;\n endLine?: number;\n message: string;\n severity: \"error\" | \"warning\";\n}\n\nexport function toFindings(result: CheckResult): Finding[] {\n return result.violations.map(violationToFinding);\n}\n\n/** Ids key on node id, not line, so a finding keeps its id when code above it moves. */\nfunction violationToFinding(v: CheckViolation): Finding {\n const tool = v.tool ?? CODE_GRAPH_TOOL;\n const target = v.destinationId ? `${v.nodeId}->${v.destinationId}` : v.nodeId;\n return withoutUndefined({\n id: `${tool}:${v.ruleId}:${target}`,\n path: v.path ?? v.nodeId,\n lineStart: v.lineStart,\n lineEnd: v.lineEnd,\n symbol: v.symbol,\n signal: v.ruleId,\n value: v.value,\n threshold: v.threshold,\n severity: v.severity,\n evidence: v.evidence ?? v.message,\n tool,\n });\n}\n\nexport function externalToFinding(input: ExternalDiagnostic): Finding {\n return withoutUndefined({\n id: `${input.tool}:${input.rule}:${input.file}:${input.line}`,\n path: input.file,\n lineStart: input.line,\n lineEnd: input.endLine,\n signal: input.rule,\n severity: input.severity,\n evidence: input.message,\n tool: input.tool,\n });\n}\n\nfunction withoutUndefined(finding: Finding): Finding {\n return Object.fromEntries(Object.entries(finding).filter(([, v]) => v !== undefined)) as Finding;\n}\n","import { createHash } from \"node:crypto\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { Finding } from \"./findings.js\";\n\nexport type VerdictLabel = \"confirmed\" | \"justified\" | \"unclear\";\n\nexport interface VerdictCitation {\n path: string;\n lineStart: number;\n lineEnd: number;\n quote: string;\n}\n\n/** A finding as stored against a snapshot, addressed by its `findingKey`. */\nexport interface StoredFinding {\n key: string;\n finding: Finding;\n /** Hash of the excerpt a reader would be shown for this finding; carry-forward compares it. */\n excerptHash?: string;\n}\n\n/** A model's judgement of one stored finding, after its citations were verified. */\nexport interface StoredVerdict {\n key: string;\n verdict: VerdictLabel;\n rationale: string;\n citations: VerdictCitation[];\n /** Hash of the excerpt the verdict judged. */\n excerptHash: string;\n model?: string;\n costUsd?: number;\n runId?: string;\n provenance?: string;\n controlRun?: \"ok\" | \"provisional\";\n dropped?: string[];\n /** The snapshot this verdict was carried from, when carry-forward copied it. */\n carriedFrom?: number;\n}\n\nexport interface FindingKeyInput {\n finding: Finding;\n /** The innermost symbol node id containing the finding; the finding's path when absent. */\n anchor?: string;\n /** The source text of the flagged lines. */\n flaggedText: string;\n excerptHash?: string;\n}\n\n/** Whitespace-insensitive, so reindenting or reflowing the flagged lines keeps the key. */\nexport function normalizeFlaggedText(text: string): string {\n return text\n .split(/\\r?\\n/)\n .map((line) => line.trim().replace(/\\s+/g, \" \"))\n .filter((line) => line.length > 0)\n .join(\"\\n\");\n}\n\nexport function hashText(text: string): string {\n return createHash(\"sha256\").update(text, \"utf8\").digest(\"hex\").slice(0, 16);\n}\n\n/**\n * A finding's identity across snapshots: no line number, so an inserted line above it\n * keeps the key, and a collision ordinal separates same-rule findings on the same text.\n */\nexport function findingKey(input: FindingKeyInput, ordinal = 0): string {\n const { finding } = input;\n const anchor = input.anchor ?? finding.path;\n const textHash = hashText(normalizeFlaggedText(input.flaggedText));\n return `${finding.tool}:${finding.signal}:${anchor}:${textHash}#${ordinal}`;\n}\n\n/** Key a whole audit's findings, numbering collisions in source order so the result ignores input order. */\nexport function keyFindings(inputs: readonly FindingKeyInput[]): StoredFinding[] {\n const ordered = [...inputs].sort(compareBySource);\n const seen = new Map<string, number>();\n return ordered.map((input) => {\n const base = findingKey(input);\n const ordinal = seen.get(base) ?? 0;\n seen.set(base, ordinal + 1);\n const stored: StoredFinding = { key: findingKey(input, ordinal), finding: input.finding };\n if (input.excerptHash !== undefined) stored.excerptHash = input.excerptHash;\n return stored;\n });\n}\n\nfunction compareBySource(a: FindingKeyInput, b: FindingKeyInput): number {\n const fa = a.finding;\n const fb = b.finding;\n return (\n fa.path.localeCompare(fb.path) ||\n (fa.lineStart ?? 0) - (fb.lineStart ?? 0) ||\n (fa.lineEnd ?? 0) - (fb.lineEnd ?? 0) ||\n (fa.evidence ?? \"\").localeCompare(fb.evidence ?? \"\") ||\n fa.id.localeCompare(fb.id)\n );\n}\n\ninterface FindingDbRow {\n key: string;\n excerpt_hash: string | null;\n attrs: string;\n}\n\ninterface VerdictDbRow {\n key: string;\n verdict: VerdictLabel;\n rationale: string;\n excerpt_hash: string;\n model: string | null;\n run_id: string | null;\n cost_usd: number | null;\n provenance: string | null;\n control_run: \"ok\" | \"provisional\" | null;\n carried_from: number | null;\n attrs: string;\n}\n\n/** Insert or replace findings by key within one snapshot. */\nexport function saveFindings(store: CodeGraphStore, snapshotId: number, findings: readonly StoredFinding[]): void {\n const insert = store.db.prepare(\n `INSERT OR REPLACE INTO finding\n (snapshot_id, key, finding_id, tool, signal, path, line_start, line_end, severity, excerpt_hash, attrs)\n VALUES (@snapshotId, @key, @findingId, @tool, @signal, @path, @lineStart, @lineEnd, @severity, @excerptHash, @attrs)`,\n );\n store.db.transaction(() => {\n for (const { key, finding, excerptHash } of findings) {\n insert.run({\n snapshotId,\n key,\n findingId: finding.id,\n tool: finding.tool,\n signal: finding.signal,\n path: finding.path,\n lineStart: finding.lineStart ?? null,\n lineEnd: finding.lineEnd ?? null,\n severity: finding.severity,\n excerptHash: excerptHash ?? null,\n attrs: JSON.stringify(finding),\n });\n }\n })();\n}\n\nexport function listFindings(store: CodeGraphStore, snapshotId: number): StoredFinding[] {\n const rows = store.db\n .prepare(\"SELECT key, excerpt_hash, attrs FROM finding WHERE snapshot_id = ? ORDER BY key\")\n .all(snapshotId) as FindingDbRow[];\n return rows.map((row) => {\n const stored: StoredFinding = { key: row.key, finding: JSON.parse(row.attrs) as Finding };\n if (row.excerpt_hash !== null) stored.excerptHash = row.excerpt_hash;\n return stored;\n });\n}\n\n/** Insert or replace verdicts by key within one snapshot. */\nexport function saveVerdicts(store: CodeGraphStore, snapshotId: number, verdicts: readonly StoredVerdict[]): void {\n const insert = store.db.prepare(\n `INSERT OR REPLACE INTO verdict\n (snapshot_id, key, verdict, rationale, excerpt_hash, model, run_id, cost_usd, provenance, control_run,\n carried_from, attrs)\n VALUES (@snapshotId, @key, @verdict, @rationale, @excerptHash, @model, @runId, @costUsd, @provenance,\n @controlRun, @carriedFrom, @attrs)`,\n );\n store.db.transaction(() => {\n for (const v of verdicts) insert.run(verdictParams(snapshotId, v));\n })();\n}\n\nfunction verdictParams(snapshotId: number, v: StoredVerdict): Record<string, unknown> {\n return {\n snapshotId,\n key: v.key,\n verdict: v.verdict,\n rationale: v.rationale,\n excerptHash: v.excerptHash,\n model: v.model ?? null,\n runId: v.runId ?? null,\n costUsd: v.costUsd ?? null,\n provenance: v.provenance ?? null,\n controlRun: v.controlRun ?? null,\n carriedFrom: v.carriedFrom ?? null,\n attrs: JSON.stringify({ citations: v.citations, dropped: v.dropped ?? [] }),\n };\n}\n\nexport function listVerdicts(store: CodeGraphStore, snapshotId: number): StoredVerdict[] {\n const rows = store.db\n .prepare(\"SELECT * FROM verdict WHERE snapshot_id = ? ORDER BY key\")\n .all(snapshotId) as VerdictDbRow[];\n return rows.map(rowToVerdict);\n}\n\nfunction rowToVerdict(row: VerdictDbRow): StoredVerdict {\n const attrs = JSON.parse(row.attrs) as { citations: VerdictCitation[]; dropped: string[] };\n const verdict: StoredVerdict = {\n key: row.key,\n verdict: row.verdict,\n rationale: row.rationale,\n citations: attrs.citations,\n excerptHash: row.excerpt_hash,\n };\n if (row.model !== null) verdict.model = row.model;\n if (row.cost_usd !== null) verdict.costUsd = row.cost_usd;\n if (row.run_id !== null) verdict.runId = row.run_id;\n if (row.provenance !== null) verdict.provenance = row.provenance;\n if (row.control_run !== null) verdict.controlRun = row.control_run;\n if (attrs.dropped.length > 0) verdict.dropped = attrs.dropped;\n if (row.carried_from !== null) verdict.carriedFrom = row.carried_from;\n return verdict;\n}\n\n/**\n * Copy each verdict of `from` onto the finding in `to` with the same key whose excerpt hash\n * equals the one the verdict judged. A verdict `to` already holds is kept. Returns the count copied.\n */\nexport function carryForwardVerdicts(store: CodeGraphStore, from: number, to: number): number {\n const targets = new Map(listFindings(store, to).map((f) => [f.key, f.excerptHash]));\n const existing = new Set(listVerdicts(store, to).map((v) => v.key));\n const carried = listVerdicts(store, from)\n .filter((v) => !existing.has(v.key) && targets.get(v.key) === v.excerptHash)\n .map((v) => ({ ...v, carriedFrom: v.carriedFrom ?? from }));\n saveVerdicts(store, to, carried);\n return carried.length;\n}\n","import { metricAliasTarget, roleAliasTarget } from \"../aliases.js\";\nimport type {\n CheckRule,\n ForbidImportRule,\n LayeredDepsRule,\n MetricMaxRule,\n MetricMinRule,\n MetricOutlierRule,\n MetricProductMaxRule,\n NoInternalOnlyBarrelsRule,\n Severity,\n} from \"./types.js\";\nimport type { NodeKind, NodeRole } from \"../types.js\";\n\nexport interface ValidateRulesOptions {\n /** Called with a human-readable message when a deprecated alias is healed. */\n onWarn?: (message: string) => void;\n}\n\ntype Warn = (message: string) => void;\n\nexport function validateRules(\n input: unknown,\n options: ValidateRulesOptions = {},\n): readonly CheckRule[] {\n if (!input || typeof input !== \"object\") {\n throw new Error(\"rules file must be an object with a `rules` array\");\n }\n const obj = input as { rules?: unknown };\n if (!Array.isArray(obj.rules)) {\n throw new Error(\"rules file must have a `rules` array\");\n }\n const warn: Warn = options.onWarn ?? (() => {});\n return obj.rules.map((r, i) => validateRule(r, i, warn));\n}\n\n/** Heal a deprecated metric name to its canonical form, warning if renamed. */\nfunction healMetricName(name: string, ruleId: string, warn: Warn): string {\n const target = metricAliasTarget(name);\n if (target) {\n warn(`${ruleId}: metric \"${name}\" is deprecated — using \"${target}\"`);\n return target;\n }\n return name;\n}\n\nfunction validateRule(raw: unknown, index: number, warn: Warn): CheckRule {\n if (!raw || typeof raw !== \"object\") {\n throw new Error(`rule[${index}] must be an object`);\n }\n const r = raw as Record<string, unknown>;\n if (typeof r.id !== \"string\" || !r.id) {\n throw new Error(`rule[${index}] missing string id`);\n }\n if (typeof r.type !== \"string\") {\n throw new Error(`rule[${index}] (${r.id}) missing string type`);\n }\n switch (r.type) {\n case \"metric-max\":\n return assertMetricMax(r, warn);\n case \"metric-min\":\n return assertMetricMin(r, warn);\n case \"metric-product-max\":\n return assertMetricProductMax(r, warn);\n case \"metric-outlier\":\n return assertMetricOutlier(r, warn);\n case \"forbid-import\":\n return assertForbidImport(r);\n case \"layered-deps\":\n return assertLayeredDeps(r);\n case \"no-internal-only-barrels\":\n return assertNoInternalOnlyBarrels(r);\n default:\n throw new Error(`rule[${index}] (${r.id}) unknown type \"${r.type}\"`);\n }\n}\n\nfunction assertNoInternalOnlyBarrels(\n r: Record<string, unknown>,\n): NoInternalOnlyBarrelsRule {\n if (!Array.isArray(r.packageRoots) || r.packageRoots.length === 0) {\n throw new Error(\n `${r.id}: packageRoots must be a non-empty array of path-prefix strings`,\n );\n }\n for (const p of r.packageRoots) {\n if (typeof p !== \"string\" || !p) {\n throw new Error(`${r.id}: each packageRoots entry must be a non-empty string`);\n }\n }\n return {\n type: \"no-internal-only-barrels\",\n id: r.id as string,\n packageRoots: r.packageRoots as string[],\n severity: r.severity as Severity | undefined,\n exclude: parseStringArray(r.exclude),\n };\n}\n\nfunction assertLayeredDeps(r: Record<string, unknown>): LayeredDepsRule {\n if (!Array.isArray(r.layers) || r.layers.length < 2) {\n throw new Error(`${r.id}: layers must be an array of 2+ string arrays`);\n }\n for (const layer of r.layers) {\n if (!Array.isArray(layer) || !layer.every((p) => typeof p === \"string\")) {\n throw new Error(`${r.id}: each layer must be a string[]`);\n }\n if (layer.length === 0) {\n throw new Error(`${r.id}: empty layers not allowed`);\n }\n }\n const seen = new Set<string>();\n for (const layer of r.layers as string[][]) {\n for (const pkg of layer) {\n if (seen.has(pkg)) {\n throw new Error(`${r.id}: package \"${pkg}\" appears in more than one layer`);\n }\n seen.add(pkg);\n }\n }\n return {\n type: \"layered-deps\",\n id: r.id as string,\n layers: r.layers as string[][],\n severity: r.severity as Severity | undefined,\n };\n}\n\nfunction assertMetricProductMax(\n r: Record<string, unknown>,\n warn: Warn,\n): MetricProductMaxRule {\n if (!Array.isArray(r.metrics) || r.metrics.length < 2) {\n throw new Error(`${r.id}: metrics must be an array of 2+ metric names`);\n }\n if (!r.metrics.every((m): m is string => typeof m === \"string\")) {\n throw new Error(`${r.id}: metrics must be strings`);\n }\n if (typeof r.max !== \"number\") {\n throw new Error(`${r.id}: max must be a number`);\n }\n const ruleId = r.id as string;\n return {\n type: \"metric-product-max\",\n id: ruleId,\n metrics: r.metrics.map((m) => healMetricName(m, ruleId, warn)),\n max: r.max,\n kind: r.kind as MetricProductMaxRule[\"kind\"],\n severity: r.severity as Severity | undefined,\n exclude: parseStringArray(r.exclude),\n excludeRoles: parseRoleArray(ruleId, r.excludeRoles, warn),\n };\n}\n\nfunction assertMetricMax(r: Record<string, unknown>, warn: Warn): MetricMaxRule {\n if (typeof r.metric !== \"string\") throw new Error(`${r.id}: metric must be a string`);\n if (typeof r.max !== \"number\") throw new Error(`${r.id}: max must be a number`);\n const ruleId = r.id as string;\n return {\n type: \"metric-max\",\n id: ruleId,\n metric: healMetricName(r.metric, ruleId, warn),\n max: r.max,\n kind: r.kind as MetricMaxRule[\"kind\"],\n severity: r.severity as Severity | undefined,\n exclude: parseStringArray(r.exclude),\n excludeRoles: parseRoleArray(ruleId, r.excludeRoles, warn),\n };\n}\n\nfunction assertMetricMin(r: Record<string, unknown>, warn: Warn): MetricMinRule {\n if (typeof r.metric !== \"string\") throw new Error(`${r.id}: metric must be a string`);\n if (typeof r.min !== \"number\") throw new Error(`${r.id}: min must be a number`);\n const ruleId = r.id as string;\n return {\n type: \"metric-min\",\n id: ruleId,\n metric: healMetricName(r.metric, ruleId, warn),\n min: r.min,\n kind: r.kind as MetricMinRule[\"kind\"],\n severity: r.severity as Severity | undefined,\n exclude: parseStringArray(r.exclude),\n excludeRoles: parseRoleArray(ruleId, r.excludeRoles, warn),\n };\n}\n\nconst NODE_KINDS: ReadonlySet<NodeKind> = new Set([\"package\", \"module\", \"file\", \"symbol\", \"external\"]);\n\nfunction assertMetricOutlier(r: Record<string, unknown>, warn: Warn): MetricOutlierRule {\n if (typeof r.metric !== \"string\") throw new Error(`${r.id}: metric must be a string`);\n if (typeof r.kind !== \"string\" || !NODE_KINDS.has(r.kind as NodeKind)) {\n throw new Error(`${r.id}: kind must be one of ${[...NODE_KINDS].join(\", \")}`);\n }\n if (typeof r.percentile !== \"number\" || r.percentile < 50 || r.percentile > 100) {\n throw new Error(`${r.id}: percentile must be a number from 50 to 100`);\n }\n if (r.minSample !== undefined && (!Number.isInteger(r.minSample) || (r.minSample as number) < 1)) {\n throw new Error(`${r.id}: minSample must be a positive integer`);\n }\n if (r.floor !== undefined && (typeof r.floor !== \"number\" || !Number.isFinite(r.floor) || r.floor < 0)) {\n throw new Error(`${r.id}: floor must be a non-negative finite number`);\n }\n if (r.rankNonZero !== undefined && typeof r.rankNonZero !== \"boolean\") {\n throw new Error(`${r.id}: rankNonZero must be a boolean`);\n }\n const ruleId = r.id as string;\n return {\n type: \"metric-outlier\",\n id: ruleId,\n metric: healMetricName(r.metric, ruleId, warn),\n kind: r.kind as NodeKind,\n percentile: r.percentile,\n minSample: r.minSample as number | undefined,\n floor: r.floor as number | undefined,\n rankNonZero: r.rankNonZero as boolean | undefined,\n severity: r.severity as Severity | undefined,\n };\n}\n\nfunction assertForbidImport(r: Record<string, unknown>): ForbidImportRule {\n if (typeof r.from !== \"string\") throw new Error(`${r.id}: from must be a string`);\n if (typeof r.to !== \"string\") throw new Error(`${r.id}: to must be a string`);\n return {\n type: \"forbid-import\",\n id: r.id as string,\n from: r.from,\n to: r.to,\n severity: r.severity as Severity | undefined,\n };\n}\n\nfunction parseStringArray(value: unknown): string[] | undefined {\n return Array.isArray(value) ? (value as string[]) : undefined;\n}\n\nconst ROLE_VALUES: ReadonlySet<NodeRole> = new Set([\n \"test\",\n \"fixture\",\n \"barrel\",\n \"types\",\n \"config\",\n \"entry\",\n \"source\",\n]);\n\nfunction parseRoleArray(\n ruleId: string,\n value: unknown,\n warn: Warn,\n): NodeRole[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value)) {\n throw new Error(`${ruleId}: excludeRoles must be an array`);\n }\n return value.map((entry) => healRole(entry, ruleId, warn));\n}\n\n/** Heal a deprecated role alias to canonical; throw only on genuinely-unknown. */\nfunction healRole(entry: unknown, ruleId: string, warn: Warn): NodeRole {\n if (typeof entry === \"string\" && ROLE_VALUES.has(entry as NodeRole)) {\n return entry as NodeRole;\n }\n if (typeof entry === \"string\") {\n const target = roleAliasTarget(entry);\n if (target) {\n warn(`${ruleId}: role \"${entry}\" is deprecated — using \"${target}\"`);\n return target;\n }\n }\n throw new Error(\n `${ruleId}: unknown role \"${entry}\" — valid: ${[...ROLE_VALUES].join(\", \")}`,\n );\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { SnapshotRow } from \"../types.js\";\nimport { runChecks } from \"./check.js\";\nimport type { CheckResult, CheckRule } from \"./types.js\";\nimport { validateRules, type ValidateRulesOptions } from \"./validate.js\";\n\n/** A snapshot id, or a ref name resolved to that ref's newest snapshot. */\nexport type SnapshotSpec = number | string;\n\nexport interface CheckSnapshotOptions {\n snapshot: SnapshotSpec;\n rules: readonly CheckRule[];\n baseline?: SnapshotSpec;\n}\n\nexport interface CheckSnapshotResult {\n snapshot: SnapshotRow;\n baselineSnapshot?: SnapshotRow;\n result: CheckResult;\n}\n\nexport function resolveSnapshot(store: CodeGraphStore, spec: SnapshotSpec): SnapshotRow {\n if (typeof spec === \"number\" || /^\\d+$/.test(spec)) {\n const snap = store.getSnapshot(Number(spec));\n if (!snap) throw new Error(`no snapshot with id ${spec}`);\n return snap;\n }\n const snap = store.getLatestSnapshotByRef(spec);\n if (!snap) throw new Error(`no snapshot found for ref \"${spec}\"`);\n return snap;\n}\n\n/** Check one snapshot against a rule set, marking violations already present in the baseline as carryover. */\nexport function checkSnapshot(store: CodeGraphStore, options: CheckSnapshotOptions): CheckSnapshotResult {\n const snapshot = resolveSnapshot(store, options.snapshot);\n const baselineSnapshot = options.baseline !== undefined ? resolveSnapshot(store, options.baseline) : undefined;\n const result = runChecks(store, {\n snapshotId: snapshot.id,\n rules: options.rules,\n baselineSnapshotId: baselineSnapshot?.id,\n });\n return { snapshot, baselineSnapshot, result };\n}\n\n/** Read and validate a `check.json` rules file; deprecated aliases heal through `onWarn`. */\nexport async function loadCheckRules(\n path: string,\n options: ValidateRulesOptions = {},\n): Promise<readonly CheckRule[]> {\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (err) {\n throw new Error(`Cannot read rules file at ${path}: ${errorMessage(err)}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new Error(`Invalid JSON in ${path}: ${errorMessage(err)}`);\n }\n return validateRules(parsed, options);\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","import { canonicalEdgeKind, canonicalMetricName } from \"../aliases.js\";\nimport type { AliasChain } from \"../identity/alias-chain.js\";\nimport { aliasChain } from \"../identity/store-identity.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { GraphEdge, GraphMetric, GraphNode } from \"../types.js\";\nimport type { GraphDiff, GraphDiffSummary, MetricDelta, NodeRename } from \"./types.js\";\n\ntype AliasMap = Pick<AliasChain, \"resolve\" | \"trace\">;\n\nfunction resolveId(id: string, aliases: AliasMap): string {\n return aliases.resolve(id);\n}\n\nfunction edgeKey(srcId: string, dstId: string, kind: string): string {\n return JSON.stringify([srcId, dstId, canonicalEdgeKind(kind)]);\n}\n\nfunction metricKey(nodeId: string, name: string): string {\n return JSON.stringify([nodeId, canonicalMetricName(name)]);\n}\n\nfunction indexEdges(edges: readonly GraphEdge[]): Map<string, GraphEdge> {\n const m = new Map<string, GraphEdge>();\n for (const e of edges) m.set(edgeKey(e.srcId, e.dstId, e.kind), e);\n return m;\n}\n\ninterface NodeDiff {\n added: GraphNode[];\n removed: GraphNode[];\n renamed: NodeRename[];\n commonNewIds: Set<string>;\n}\n\nfunction diffNodes(fromNodes: readonly GraphNode[], toNodes: readonly GraphNode[], aliases: AliasMap): NodeDiff {\n const toIndex = new Map(toNodes.map((n) => [n.id, n]));\n const matchedToIds = new Set<string>();\n const removed: GraphNode[] = [];\n const renamed: NodeRename[] = [];\n for (const fromNode of fromNodes) {\n const newId = resolveId(fromNode.id, aliases);\n const toNode = toIndex.get(newId);\n if (!toNode) {\n removed.push(fromNode);\n continue;\n }\n matchedToIds.add(newId);\n if (newId !== fromNode.id) {\n renamed.push({ oldId: fromNode.id, newId, reason: aliases.trace(fromNode.id).reason!, node: toNode });\n }\n }\n const added = toNodes.filter((toNode) => !matchedToIds.has(toNode.id));\n return { added, removed, renamed, commonNewIds: matchedToIds };\n}\n\nfunction diffEdges(\n fromEdges: readonly GraphEdge[],\n toEdges: readonly GraphEdge[],\n aliases: AliasMap,\n): { added: GraphEdge[]; removed: GraphEdge[] } {\n const remappedKey = (e: GraphEdge) => edgeKey(resolveId(e.srcId, aliases), resolveId(e.dstId, aliases), e.kind);\n const fromKeys = new Set(fromEdges.map(remappedKey));\n const toIndex = indexEdges(toEdges);\n const added: GraphEdge[] = [];\n for (const [k, e] of toIndex) {\n if (!fromKeys.has(k)) added.push(e);\n }\n const removed = fromEdges.filter((e) => !toIndex.has(remappedKey(e)));\n return { added, removed };\n}\n\ninterface IndexedMetric {\n metric: GraphMetric;\n nodeId: string;\n}\n\nfunction indexFromMetrics(metrics: readonly GraphMetric[], aliases: AliasMap): Map<string, IndexedMetric> {\n const fromIndex = new Map<string, IndexedMetric>();\n for (const m of metrics) {\n const newId = resolveId(m.nodeId, aliases);\n fromIndex.set(metricKey(newId, m.name), { metric: m, nodeId: newId });\n }\n return fromIndex;\n}\n\nfunction deltaOf(before: number | null, after: number | null): number | null {\n if (before === null || after === null) return null;\n return after - before;\n}\n\nfunction metricDelta(nodeId: string, name: string, before: number | null, after: number | null): MetricDelta {\n return { nodeId, name: canonicalMetricName(name), before, after, delta: deltaOf(before, after) };\n}\n\n/** Metric changes on nodes present in both snapshots; metrics on added or removed nodes are the node's news, not drift. */\nfunction diffMetrics(\n fromMetrics: readonly GraphMetric[],\n toMetrics: readonly GraphMetric[],\n aliases: AliasMap,\n commonNewIds: Set<string>,\n): MetricDelta[] {\n const fromIndex = indexFromMetrics(fromMetrics, aliases);\n const toIndex = new Map(toMetrics.map((m) => [metricKey(m.nodeId, m.name), m]));\n const out: MetricDelta[] = [];\n const seen = new Set<string>();\n for (const [key, { metric: before, nodeId }] of fromIndex) {\n if (!commonNewIds.has(nodeId)) continue;\n seen.add(key);\n const afterVal = toIndex.get(key)?.value ?? null;\n if (before.value !== afterVal) out.push(metricDelta(nodeId, before.name, before.value, afterVal));\n }\n for (const [key, after] of toIndex) {\n if (seen.has(key) || !commonNewIds.has(after.nodeId)) continue;\n out.push(metricDelta(after.nodeId, after.name, null, after.value));\n }\n return out;\n}\n\nexport interface DiffSnapshotsOptions {\n fromSnapshotId: number;\n toSnapshotId: number;\n}\n\n/**\n * Structural diff of two snapshots. Ids follow the alias chain between them, across\n * every rename in between, so a move is not a delete plus an add.\n */\nexport function diffSnapshots(store: CodeGraphStore, options: DiffSnapshotsOptions): GraphDiff {\n const { fromSnapshotId, toSnapshotId } = options;\n const aliases = aliasChain(store, fromSnapshotId, toSnapshotId);\n const nodeDiff = diffNodes(store.listNodes(fromSnapshotId), store.listNodes(toSnapshotId), aliases);\n const edgeDiff = diffEdges(store.listEdges(fromSnapshotId), store.listEdges(toSnapshotId), aliases);\n const metricDeltas = diffMetrics(\n store.listMetrics(fromSnapshotId),\n store.listMetrics(toSnapshotId),\n aliases,\n nodeDiff.commonNewIds,\n );\n return {\n summary: summarize(options, nodeDiff, edgeDiff, metricDeltas),\n addedNodes: nodeDiff.added,\n removedNodes: nodeDiff.removed,\n renamedNodes: nodeDiff.renamed,\n addedEdges: edgeDiff.added,\n removedEdges: edgeDiff.removed,\n metricDeltas,\n };\n}\n\nfunction summarize(\n { fromSnapshotId, toSnapshotId }: DiffSnapshotsOptions,\n nodeDiff: NodeDiff,\n edgeDiff: { added: GraphEdge[]; removed: GraphEdge[] },\n metricDeltas: readonly MetricDelta[],\n): GraphDiffSummary {\n return {\n fromSnapshotId,\n toSnapshotId,\n addedNodes: nodeDiff.added.length,\n removedNodes: nodeDiff.removed.length,\n renamedNodes: nodeDiff.renamed.length,\n unchangedNodes: nodeDiff.commonNewIds.size - nodeDiff.renamed.length,\n addedEdges: edgeDiff.added.length,\n removedEdges: edgeDiff.removed.length,\n metricChanges: metricDeltas.length,\n };\n}\n","import { rebasedViolationKey, runChecks, violationKey } from \"../check/check.js\";\nimport type { CheckRule, CheckViolation } from \"../check/types.js\";\nimport { aliasChain } from \"../identity/store-identity.js\";\nimport type { CodeGraphStore } from \"../store.js\";\n\nexport interface UnchangedViolation {\n from: CheckViolation;\n to: CheckViolation;\n delta: number | null;\n}\n\nexport interface CheckDiff {\n fromSnapshotId: number;\n toSnapshotId: number;\n rulesEvaluated: number;\n newViolations: CheckViolation[];\n resolvedViolations: CheckViolation[];\n unchanged: UnchangedViolation[];\n worsened: UnchangedViolation[];\n improved: UnchangedViolation[];\n}\n\nexport interface DiffCheckResultsOptions {\n fromSnapshotId: number;\n toSnapshotId: number;\n rules: readonly CheckRule[];\n}\n\ntype Buckets = Pick<CheckDiff, \"newViolations\" | \"resolvedViolations\" | \"unchanged\" | \"worsened\" | \"improved\">;\n\n/**\n * Run the rules on both snapshots and bucket each violation as new, resolved, or\n * unchanged (worsened or improved by value). From-side ids follow the alias chain\n * into the to-snapshot, so a moved file's violations stay unchanged.\n */\nexport function diffCheckResults(store: CodeGraphStore, options: DiffCheckResultsOptions): CheckDiff {\n const from = runChecks(store, { snapshotId: options.fromSnapshotId, rules: options.rules });\n const to = runChecks(store, { snapshotId: options.toSnapshotId, rules: options.rules });\n const chain = aliasChain(store, options.fromSnapshotId, options.toSnapshotId);\n return {\n fromSnapshotId: options.fromSnapshotId,\n toSnapshotId: options.toSnapshotId,\n rulesEvaluated: options.rules.length,\n ...bucketViolations(indexByKey(from.violations, chain.resolve), indexByKey(to.violations)),\n };\n}\n\nfunction bucketViolations(\n fromByKey: Map<string, CheckViolation>,\n toByKey: Map<string, CheckViolation>,\n): Buckets {\n const buckets: Buckets = { newViolations: [], resolvedViolations: [], unchanged: [], worsened: [], improved: [] };\n for (const [key, toV] of toByKey) {\n const fromV = fromByKey.get(key);\n if (!fromV) {\n buckets.newViolations.push(toV);\n continue;\n }\n const delta = computeDelta(fromV, toV);\n const entry: UnchangedViolation = { from: fromV, to: toV, delta };\n buckets.unchanged.push(entry);\n if (delta !== null && delta > 0) buckets.worsened.push(entry);\n else if (delta !== null && delta < 0) buckets.improved.push(entry);\n }\n for (const [key, fromV] of fromByKey) {\n if (!toByKey.has(key)) buckets.resolvedViolations.push(fromV);\n }\n return buckets;\n}\n\nfunction indexByKey(\n violations: readonly CheckViolation[],\n resolve?: (id: string) => string,\n): Map<string, CheckViolation> {\n const out = new Map<string, CheckViolation>();\n for (const v of violations) out.set(resolve ? rebasedViolationKey(v, resolve) : violationKey(v), v);\n return out;\n}\n\nfunction computeDelta(from: CheckViolation, to: CheckViolation): number | null {\n if (from.value === undefined || to.value === undefined) return null;\n return to.value - from.value;\n}\n","import { canonicalEdgeKind } from \"../aliases.js\";\nimport {\n computeSymbolConsumers,\n computeSymbolCoupling,\n type ReferenceEdgeLite,\n} from \"../analysis/symbol-coupling.js\";\nimport { hashText } from \"../check/finding-store.js\";\nimport type { GraphEdge, GraphNode } from \"../types.js\";\n\n/**\n * A symbol's documentable footprint (C-75): structural inputs only, so a moved declaration,\n * a churn window or a centrality shift never reads as a change.\n */\nexport interface FootprintParts {\n /** Hash of `{name, exported, signature, purpose}`; no span. */\n signature: string;\n /** Hash of the sorted distinct file ids that reference the symbol. */\n consumers: string;\n /** Hash of the sorted co-import partner symbol ids at or above `minCoImports`. */\n coupling: string;\n}\n\nexport interface SymbolFootprint {\n symbolId: string;\n parts: FootprintParts;\n /** Hash of the three part hashes. */\n hash: string;\n}\n\nexport interface FootprintGraph {\n nodes: readonly GraphNode[];\n edges: readonly GraphEdge[];\n}\n\nexport interface FootprintOptions {\n /** Drop a referencing file from consumers and co-import coupling, e.g. test files. Default keeps all. */\n ignoreConsumer?: (fileId: string) => boolean;\n /** Co-import threshold for a coupling partner. Default 2. */\n minCoImports?: number;\n}\n\n/** A doc target: the default unit is one file holding its symbols. */\nexport interface FootprintUnit {\n unitId: string;\n symbolIds: readonly string[];\n}\n\nconst DEFAULT_MIN_CO_IMPORTS = 2;\n\n/** Footprint of every symbol node in the graph, keyed by symbol id. */\nexport function computeFootprints(\n graph: FootprintGraph,\n options: FootprintOptions = {},\n): Map<string, SymbolFootprint> {\n const edges = referenceEdges(graph.edges, options.ignoreConsumer);\n const consumers = consumersBySymbol(edges);\n const partners = partnersBySymbol(edges, options.minCoImports ?? DEFAULT_MIN_CO_IMPORTS);\n const out = new Map<string, SymbolFootprint>();\n for (const node of graph.nodes) {\n if (node.kind !== \"symbol\") continue;\n const parts: FootprintParts = {\n signature: hashJson(signatureOf(node)),\n consumers: hashJson(consumers.get(node.id) ?? []),\n coupling: hashJson(partners.get(node.id) ?? []),\n };\n const hash = hashJson([parts.signature, parts.consumers, parts.coupling]);\n out.set(node.id, { symbolId: node.id, parts, hash });\n }\n return out;\n}\n\n/**\n * Order-independent hash of a unit's `[symbolId, footprint.hash]` pairs. A member with no\n * footprint hashes as null, so a symbol that disappears still changes the set.\n */\nexport function symbolSetHash(\n unit: FootprintUnit,\n footprints: ReadonlyMap<string, SymbolFootprint>,\n): string {\n const pairs = [...new Set(unit.symbolIds)]\n .sort()\n .map((id) => [id, footprints.get(id)?.hash ?? null]);\n return hashJson(pairs);\n}\n\nfunction hashJson(value: unknown): string {\n return hashText(JSON.stringify(value));\n}\n\nfunction signatureOf(node: GraphNode): unknown {\n const attrs = node.attrs ?? {};\n return {\n name: node.name,\n exported: attrs.exported === true,\n signature: typeof attrs.signature === \"string\" ? attrs.signature : null,\n purpose: typeof attrs.purpose === \"string\" ? attrs.purpose : null,\n };\n}\n\nfunction referenceEdges(\n edges: readonly GraphEdge[],\n ignoreConsumer: FootprintOptions[\"ignoreConsumer\"],\n): ReferenceEdgeLite[] {\n return edges.filter(\n (e) => canonicalEdgeKind(e.kind) === \"references\" && !ignoreConsumer?.(e.srcId),\n );\n}\n\nfunction consumersBySymbol(edges: readonly ReferenceEdgeLite[]): Map<string, string[]> {\n return new Map(computeSymbolConsumers(edges).map((c) => [c.symbolId, c.consumers]));\n}\n\nfunction partnersBySymbol(\n edges: readonly ReferenceEdgeLite[],\n minCoImports: number,\n): Map<string, string[]> {\n const partners = new Map<string, Set<string>>();\n const add = (from: string, to: string): void => {\n const set = partners.get(from) ?? new Set<string>();\n set.add(to);\n partners.set(from, set);\n };\n for (const pair of computeSymbolCoupling(edges, { minCoImports })) {\n add(pair.aId, pair.bId);\n add(pair.bId, pair.aId);\n }\n return new Map([...partners].map(([id, set]) => [id, [...set].sort()]));\n}\n","import { contentHashOf } from \"@titan-design/store-sqlite\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { GraphNode } from \"../types.js\";\nimport type { EmbeddableSymbol } from \"./types.js\";\n\n/** Mirrors the gate harness: purpose text is appended to the signature when present. */\nexport function buildEmbedText(signature: string, purpose?: string | null): string {\n return purpose ? `${signature} -- ${purpose}` : signature;\n}\n\nexport function hashEmbedText(text: string): string {\n return contentHashOf(text);\n}\n\nconst TEST_OR_FIXTURE_PATH = /\\.test\\.|\\.spec\\.|__tests__|\\/fixtures\\//;\nconst EXCLUDED_FILE_ROLES = new Set([\"test\", \"generated\"]);\n\ninterface SymbolTextAttrs {\n exported?: boolean;\n signature?: string;\n purpose?: string;\n}\n\n/**\n * The embeddable corpus of a snapshot: exported symbols that carry a signature,\n * excluding test/fixture/generated code (matching the validated gate corpus).\n */\nexport function listEmbeddableSymbols(store: CodeGraphStore, snapshotId: number): EmbeddableSymbol[] {\n const nodes = store.listNodes(snapshotId, { includeSymbols: true });\n const fileRoles = new Map<string, string | null>();\n for (const n of nodes) if (n.kind === \"file\") fileRoles.set(n.id, n.role ?? null);\n const out: EmbeddableSymbol[] = [];\n for (const n of nodes) {\n const symbol = toEmbeddable(n, fileRoles);\n if (symbol) out.push(symbol);\n }\n return out;\n}\n\nfunction toEmbeddable(node: GraphNode, fileRoles: ReadonlyMap<string, string | null>): EmbeddableSymbol | null {\n if (node.kind !== \"symbol\") return null;\n const attrs = (node.attrs ?? {}) as SymbolTextAttrs;\n if (attrs.exported !== true || !attrs.signature) return null;\n const file = node.parentId ?? node.id.split(\"#\")[0] ?? node.id;\n if (TEST_OR_FIXTURE_PATH.test(file)) return null;\n const role = fileRoles.get(file);\n if (role && EXCLUDED_FILE_ROLES.has(role)) return null;\n const text = buildEmbedText(attrs.signature, attrs.purpose);\n return {\n id: node.id,\n name: node.name,\n file,\n signature: attrs.signature,\n purpose: attrs.purpose,\n text,\n textHash: hashEmbedText(text),\n };\n}\n","import { fromFloat32Buffer, normalize, toFloat32Buffer, type Embedder } from \"@titan-design/embed\";\nimport { CacheBlobTable } from \"@titan-design/store-sqlite\";\nimport { KIT } from \"../schema.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { hashEmbedText } from \"./corpus.js\";\n\n/** The blob_cache namespace for symbol vectors; the model column holds `embedder.model`, which names the vector space including its prefixes. */\nexport const SYMBOL_EMBEDDING_NAMESPACE = \"code-graph/symbol-embedding\";\n\nconst EMBED_BATCH_SIZE = 64;\n\nexport interface CachedEmbedResult {\n /** L2-normalized vectors for every input text, keyed by its text hash. */\n byHash: Map<string, number[]>;\n /** Hashes that had no stored vector and were embedded on this call. */\n newHashes: Set<string>;\n}\n\nfunction symbolVectorCache(store: CodeGraphStore): CacheBlobTable {\n return new CacheBlobTable(store.db, { name: KIT.cacheBlob });\n}\n\nexport function loadVectorsByHash(\n store: CodeGraphStore,\n model: string,\n hashes: readonly string[],\n): Map<string, number[]> {\n const cache = symbolVectorCache(store);\n const found = new Map<string, number[]>();\n for (const contentHash of new Set(hashes)) {\n const hit = cache.get({ namespace: SYMBOL_EMBEDDING_NAMESPACE, model, contentHash });\n if (hit) found.set(contentHash, fromFloat32Buffer(hit.value));\n }\n return found;\n}\n\nfunction storeVectors(\n store: CodeGraphStore,\n model: string,\n rows: ReadonlyArray<{ textHash: string; vector: number[] }>,\n): void {\n const cache = symbolVectorCache(store);\n store.db.transaction(() => {\n for (const r of rows) {\n const key = { namespace: SYMBOL_EMBEDDING_NAMESPACE, model, contentHash: r.textHash };\n cache.put(key, toFloat32Buffer(r.vector), { dims: r.vector.length });\n }\n })();\n}\n\n/**\n * Embed texts through the content-addressed store: only texts whose hash has\n * no vector for this model reach the embedder; new vectors are normalized and\n * persisted batch by batch so the next call (or a retry after a failure) is a cache hit.\n */\nexport async function embedTextsCached(\n store: CodeGraphStore,\n embedder: Embedder,\n texts: readonly string[],\n): Promise<CachedEmbedResult> {\n const hashes = texts.map((t) => hashEmbedText(t));\n const byHash = loadVectorsByHash(store, embedder.model, hashes);\n const missing = new Map<string, string>();\n texts.forEach((text, i) => {\n if (!byHash.has(hashes[i]!)) missing.set(hashes[i]!, text);\n });\n const pending = [...missing.entries()];\n for (let i = 0; i < pending.length; i += EMBED_BATCH_SIZE) {\n const rows = await embedBatch(embedder, pending.slice(i, i + EMBED_BATCH_SIZE));\n storeVectors(store, embedder.model, rows);\n for (const r of rows) byHash.set(r.textHash, r.vector);\n }\n return { byHash, newHashes: new Set(missing.keys()) };\n}\n\nasync function embedBatch(\n embedder: Embedder,\n batch: ReadonlyArray<[string, string]>,\n): Promise<Array<{ textHash: string; vector: number[] }>> {\n const vectors = await embedder.embed(batch.map(([, text]) => text), { role: \"document\" });\n if (vectors.length !== batch.length) {\n throw new Error(`Embedder returned ${vectors.length} vectors for ${batch.length} texts`);\n }\n return batch.map(([textHash], j) => ({ textHash, vector: normalize(vectors[j]!) }));\n}\n","import type { Embedder } from \"@titan-design/embed\";\nimport { BruteForceVectorIndex, vectorRetriever } from \"@titan-design/retrieval\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { embedTextsCached, loadVectorsByHash } from \"./cache.js\";\nimport { listEmbeddableSymbols } from \"./corpus.js\";\nimport type {\n EmbedAttempt,\n EmbeddableSymbol,\n EmbedSnapshotResult,\n FindSimilarOptions,\n SimilarCandidate,\n SimilarResult,\n} from \"./types.js\";\n\n/**\n * Precompute capability embeddings for a snapshot. Only texts whose hash has no\n * stored vector are sent to the embedder, so re-runs and unchanged symbols cost\n * nothing: the content-addressed store is the incremental-reuse mechanism.\n */\nexport async function embedSnapshot(\n store: CodeGraphStore,\n snapshotId: number,\n embedder: Embedder,\n): Promise<EmbedSnapshotResult> {\n const symbols = listEmbeddableSymbols(store, snapshotId);\n const { newHashes } = await embedTextsCached(store, embedder, symbols.map((s) => s.text));\n return {\n model: embedder.model,\n symbols: symbols.length,\n withPurpose: symbols.filter((s) => s.purpose).length,\n embedded: symbols.length,\n newlyEmbedded: newHashes.size,\n reused: symbols.filter((s) => !newHashes.has(s.textHash)).length,\n };\n}\n\n/**\n * The post-index pass. A backend failure (ollama down, model missing) must not\n * fail the index: the snapshot is already persisted and valid without vectors.\n */\nexport async function tryEmbedSnapshot(\n store: CodeGraphStore,\n snapshotId: number,\n embedder: Embedder,\n): Promise<EmbedAttempt> {\n try {\n return { ok: true, result: await embedSnapshot(store, snapshotId, embedder) };\n } catch (err) {\n return { ok: false, model: embedder.model, error: err instanceof Error ? err.message : String(err) };\n }\n}\n\n/**\n * The query-time \"about to write X: does it exist?\" surface. Embeds the query\n * (an intent sentence, a pseudo-signature, or both as `sig -- intent`), ranks\n * the snapshot's embedded symbols by cosine similarity, and returns the top-K\n * with coverage so the caller can weigh how much of the repo was searchable.\n */\nexport async function findSimilarCapability(\n store: CodeGraphStore,\n snapshotId: number,\n query: string,\n embedder: Embedder,\n opts: FindSimilarOptions = {},\n): Promise<SimilarResult> {\n const symbols = listEmbeddableSymbols(store, snapshotId);\n const index = buildSymbolIndex(store, embedder.model, symbols);\n if (index.size === 0) {\n throw new Error(\n `No capability embeddings stored for snapshot ${snapshotId} ` +\n `(model ${embedder.model}); run embedSnapshot first.`,\n );\n }\n const retriever = vectorRetriever(embedder, index);\n const hits = await retriever.retrieve(query, { limit: opts.limit ?? 10 });\n const byId = new Map(symbols.map((s) => [s.id, s]));\n return {\n query,\n model: embedder.model,\n coverage: { symbols: symbols.length, embedded: index.size, withPurpose: symbols.filter((s) => s.purpose).length },\n candidates: hits.map((h) => toCandidate(byId.get(h.id)!, h.score ?? 0)),\n };\n}\n\nfunction buildSymbolIndex(\n store: CodeGraphStore,\n model: string,\n symbols: readonly EmbeddableSymbol[],\n): BruteForceVectorIndex {\n const vectors = loadVectorsByHash(store, model, symbols.map((s) => s.textHash));\n const index = new BruteForceVectorIndex();\n for (const s of symbols) {\n const vector = vectors.get(s.textHash);\n if (vector) index.add(s.id, vector);\n }\n return index;\n}\n\nfunction toCandidate(s: EmbeddableSymbol, score: number): SimilarCandidate {\n return { id: s.id, name: s.name, file: s.file, signature: s.signature, purpose: s.purpose, score };\n}\n","import type { GraphEdge } from \"../types.js\";\n\n/**\n * Greedy-modularity (Clauset-Newman-Moore) community detection over the\n * undirected file dependency graph. Deterministic: ties and labels resolve\n * by sorted node id, so the same graph always yields the same partition.\n *\n * Two optional controls shape the C-88 capability-altitude cut, in opposite\n * directions: `maxSize` skips any merge that would grow a community past it\n * (greedy CNM otherwise snowballs a dense graph into one giant blob — the\n * cap shapes formation instead of trying to split after the fact), and\n * `targetCount` keeps merging past the natural modularity stop (taking the\n * least-bad allowed merge) while more communities than that remain, so a\n * sparse fragmented graph still coarsens. Disconnected components can never\n * merge, so the floor is the component count.\n */\nexport function detectCommunities(\n fileIds: readonly string[],\n edges: readonly GraphEdge[],\n opts?: { targetCount?: number; maxSize?: number },\n): Map<string, string[]> {\n const nodeSet = new Set(fileIds);\n const adj = buildUndirectedAdjacency(edges, nodeSet);\n const communityOf = greedyModularity(fileIds, adj, opts);\n const out = new Map<string, string[]>();\n for (const f of fileIds) pushMulti(out, communityOf.get(f) ?? f, f);\n return out;\n}\n\nfunction buildUndirectedAdjacency(\n edges: readonly GraphEdge[],\n nodeSet: ReadonlySet<string>,\n): Map<string, Map<string, number>> {\n const adj = new Map<string, Map<string, number>>();\n const link = (a: string, b: string): void => {\n let row = adj.get(a);\n if (!row) {\n row = new Map();\n adj.set(a, row);\n }\n row.set(b, (row.get(b) ?? 0) + 1);\n };\n for (const e of edges) {\n if (e.srcId === e.dstId) continue;\n if (!nodeSet.has(e.srcId) || !nodeSet.has(e.dstId)) continue;\n link(e.srcId, e.dstId);\n link(e.dstId, e.srcId);\n }\n return adj;\n}\n\ninterface CommunityState {\n members: Map<string, string[]>;\n deg: Map<string, number>;\n between: Map<string, Map<string, number>>;\n twoM: number;\n}\n\nfunction greedyModularity(\n nodes: readonly string[],\n adj: ReadonlyMap<string, ReadonlyMap<string, number>>,\n opts?: { targetCount?: number; maxSize?: number },\n): Map<string, string> {\n const state = initCommunities(nodes, adj);\n if (state.twoM === 0) return new Map(nodes.map((n) => [n, n]));\n for (;;) {\n const coarsen =\n opts?.targetCount !== undefined && state.members.size > opts.targetCount;\n const best = bestMerge(state, coarsen, opts?.maxSize);\n if (!best) break;\n applyMerge(state, best.i, best.j);\n }\n return communityLabels(state);\n}\n\nfunction initCommunities(\n nodes: readonly string[],\n adj: ReadonlyMap<string, ReadonlyMap<string, number>>,\n): CommunityState {\n const members = new Map<string, string[]>();\n const deg = new Map<string, number>();\n const between = new Map<string, Map<string, number>>();\n let twoM = 0;\n for (const n of nodes) {\n const row = new Map<string, number>();\n let d = 0;\n for (const [k, w] of adj.get(n) ?? []) {\n row.set(k, w);\n d += w;\n }\n members.set(n, [n]);\n deg.set(n, d);\n between.set(n, row);\n twoM += d;\n }\n return { members, deg, between, twoM };\n}\n\n/**\n * The adjacent community pair with the largest modularity gain, among merges\n * that respect `maxSize`. Without `allowNegative`, only positive-gain merges\n * qualify (the natural CNM stop); with it, the least-bad allowed merge is\n * returned so coarsening can continue.\n */\nfunction bestMerge(\n state: CommunityState,\n allowNegative: boolean,\n maxSize?: number,\n): { i: string; j: string; dQ: number } | null {\n const { members, between, deg, twoM } = state;\n let best: { i: string; j: string; dQ: number } | null = null;\n for (const [i, row] of between) {\n for (const [j, eij] of row) {\n if (i >= j) continue;\n if (\n maxSize !== undefined &&\n members.get(i)!.length + members.get(j)!.length > maxSize\n ) {\n continue;\n }\n const dQ =\n (2 * eij) / twoM -\n (2 * deg.get(i)! * deg.get(j)!) / (twoM * twoM);\n if (!allowNegative && dQ <= 1e-12) continue;\n if (best === null || dQ > best.dQ) best = { i, j, dQ };\n }\n }\n return best;\n}\n\nfunction applyMerge(state: CommunityState, i: string, j: string): void {\n const { members, deg, between } = state;\n members.get(i)!.push(...members.get(j)!);\n members.delete(j);\n deg.set(i, deg.get(i)! + deg.get(j)!);\n deg.delete(j);\n const rowI = between.get(i)!;\n for (const [k, w] of between.get(j)!) {\n if (k === i) continue;\n rowI.set(k, (rowI.get(k) ?? 0) + w);\n const rowK = between.get(k)!;\n rowK.set(i, (rowK.get(i) ?? 0) + w);\n rowK.delete(j);\n }\n rowI.delete(j);\n between.delete(j);\n}\n\nfunction communityLabels(state: CommunityState): Map<string, string> {\n const out = new Map<string, string>();\n const reps = [...state.members.keys()].sort();\n reps.forEach((rep, idx) => {\n for (const n of state.members.get(rep)!) out.set(n, `c${idx}`);\n });\n return out;\n}\n\nfunction pushMulti(map: Map<string, string[]>, key: string, value: string): void {\n let list = map.get(key);\n if (!list) {\n list = [];\n map.set(key, list);\n }\n list.push(value);\n}\n","import * as path from \"node:path\";\nimport { contentHashOf } from \"@titan-design/store-sqlite\";\nimport { resolveBarrelEdges } from \"../barrel-resolve.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { GraphEdge, GraphNode } from \"../types.js\";\nimport { detectCommunities } from \"./communities.js\";\nimport type { ConventionArea, ConventionCorpus, ConventionOptions, ConventionSymbol } from \"./types.js\";\n\nconst DEFAULT_MIN_SIZE = 3;\nconst PROMPT_FILE_CAP = 30;\nconst PROMPT_SYMBOL_CAP = 15;\n\n/** Coarse capability-altitude cut: about one area per 25 files, clamped to 6..40. */\nexport function defaultTargetCount(fileCount: number): number {\n return Math.min(40, Math.max(6, Math.ceil(fileCount / 25)));\n}\n\n/**\n * The deterministic half of the convention layer: partition the barrel-resolved\n * file graph into coarse areas and build each area's summarizer prompt and cache key.\n */\nexport function buildConventionAreas(\n store: CodeGraphStore,\n snapshotId: number,\n opts?: ConventionOptions,\n): ConventionCorpus {\n const nodes = store.listNodes(snapshotId, { includeSymbols: true });\n const { files, edges } = resolvedFileGraph(store, snapshotId, nodes);\n const symbolsByFile = collectExportedSymbols(nodes);\n const areas: ConventionArea[] = [];\n const prompts = new Map<string, string>();\n for (const members of partitionFiles(files, edges, opts)) {\n const { area, prompt } = buildArea(members, edges, symbolsByFile);\n areas.push(area);\n prompts.set(area.contentHash, prompt);\n }\n const grouped = areas.reduce((s, a) => s + a.size, 0);\n return { areas, prompts, coverage: { files: files.length, grouped, areas: areas.length, summarized: 0 } };\n}\n\nfunction resolvedFileGraph(\n store: CodeGraphStore,\n snapshotId: number,\n nodes: readonly GraphNode[],\n): { files: string[]; edges: GraphEdge[] } {\n const files = nodes\n .filter((n) => n.kind === \"file\" && n.role !== \"generated\")\n .map((n) => n.id)\n .sort();\n const fileSet = new Set(files);\n const edges = resolveBarrelEdges(nodes, store.listEdges(snapshotId)).filter(\n (e) => e.srcId !== e.dstId && fileSet.has(e.srcId) && fileSet.has(e.dstId),\n );\n return { files, edges };\n}\n\nfunction partitionFiles(files: readonly string[], edges: readonly GraphEdge[], opts?: ConventionOptions): string[][] {\n const target = opts?.targetCount ?? defaultTargetCount(files.length);\n const minSize = opts?.minSize ?? DEFAULT_MIN_SIZE;\n // A 2x cap on the ideal share keeps a dense repo from snowballing into one indescribable area.\n const maxSize = Math.max(minSize * 2, Math.ceil((files.length / target) * 2));\n return [...detectCommunities(files, edges, { targetCount: target, maxSize }).values()]\n .filter((members) => members.length >= minSize)\n .sort(bySizeThenFirstFile);\n}\n\nfunction bySizeThenFirstFile(a: string[], b: string[]): number {\n if (a.length !== b.length) return b.length - a.length;\n return (a[0] ?? \"\") < (b[0] ?? \"\") ? -1 : 1;\n}\n\ninterface SymbolAttrs {\n exported?: boolean;\n signature?: string;\n purpose?: string;\n}\n\nfunction collectExportedSymbols(nodes: readonly GraphNode[]): Map<string, ConventionSymbol[]> {\n const byFile = new Map<string, ConventionSymbol[]>();\n for (const n of nodes) {\n if (n.kind !== \"symbol\") continue;\n const attrs = (n.attrs ?? {}) as SymbolAttrs;\n if (attrs.exported !== true || !attrs.signature) continue;\n const file = n.parentId ?? n.id.split(\"#\")[0] ?? n.id;\n const list = byFile.get(file) ?? [];\n list.push({ name: n.name, signature: attrs.signature, purpose: attrs.purpose });\n byFile.set(file, list);\n }\n return byFile;\n}\n\nfunction buildArea(\n members: readonly string[],\n edges: readonly GraphEdge[],\n symbolsByFile: ReadonlyMap<string, ConventionSymbol[]>,\n): { area: ConventionArea; prompt: string } {\n const files = rankByDegree(members, edges);\n const label = dominantDirectory(files);\n const topSymbols = pickTopSymbols(files, symbolsByFile);\n const prompt = buildPrompt(label, files, topSymbols);\n const area: ConventionArea = {\n id: `area-${contentHashOf(files.join(\"\\n\")).slice(0, 8)}`,\n label,\n files,\n size: files.length,\n topSymbols,\n contentHash: contentHashOf(prompt),\n };\n return { area, prompt };\n}\n\nfunction rankByDegree(members: readonly string[], edges: readonly GraphEdge[]): string[] {\n const memberSet = new Set(members);\n const degree = new Map<string, number>();\n for (const e of edges) {\n if (!memberSet.has(e.srcId) || !memberSet.has(e.dstId)) continue;\n degree.set(e.srcId, (degree.get(e.srcId) ?? 0) + 1);\n degree.set(e.dstId, (degree.get(e.dstId) ?? 0) + 1);\n }\n return [...members].sort((a, b) => {\n const d = (degree.get(b) ?? 0) - (degree.get(a) ?? 0);\n return d !== 0 ? d : a < b ? -1 : 1;\n });\n}\n\nfunction dominantDirectory(files: readonly string[]): string {\n const counts = new Map<string, number>();\n for (const f of files) {\n const dir = path.posix.dirname(f);\n counts.set(dir, (counts.get(dir) ?? 0) + 1);\n }\n const dirs = [...counts.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1));\n const topDir = dirs[0]?.[0] ?? \".\";\n return dirs.length > 1 ? `${topDir} (+${dirs.length - 1} dirs)` : topDir;\n}\n\nfunction pickTopSymbols(\n rankedFiles: readonly string[],\n symbolsByFile: ReadonlyMap<string, ConventionSymbol[]>,\n): ConventionSymbol[] {\n const out: ConventionSymbol[] = [];\n for (const file of rankedFiles) {\n for (const sym of symbolsByFile.get(file) ?? []) {\n out.push(sym);\n if (out.length >= PROMPT_SYMBOL_CAP) return out;\n }\n }\n return out;\n}\n\nfunction buildPrompt(label: string, files: readonly string[], symbols: readonly ConventionSymbol[]): string {\n const shown = files.slice(0, PROMPT_FILE_CAP);\n const lines = [\n 'You are writing one entry of a repository \"convention map\" — a',\n \"capability-altitude summary coding agents read at PLAN time to learn how\",\n \"this repo does things and where new code belongs.\",\n \"\",\n `Capability area: ${label}`,\n `Files (${files.length}):`,\n ...shown.map((f) => `- ${f}`),\n ];\n if (files.length > shown.length) lines.push(`- …and ${files.length - shown.length} more`);\n if (symbols.length > 0) {\n lines.push(\"Key exported symbols:\");\n for (const s of symbols) lines.push(`- ${s.signature}${s.purpose ? ` — ${s.purpose}` : \"\"}`);\n }\n lines.push(\n \"\",\n \"Write 2-3 sentences: (1) what this area does, and (2) HOW — the key entry\",\n \"points, patterns and conventions to follow when adding related code.\",\n \"Plain text only, no preamble or headings.\",\n );\n return lines.join(\"\\n\");\n}\n","import { CacheBlobTable } from \"@titan-design/store-sqlite\";\nimport { KIT } from \"../schema.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { buildConventionAreas } from \"./areas.js\";\nimport type {\n ConventionArea,\n ConventionMap,\n ConventionOptions,\n SummarizeConventionsResult,\n Summarizer,\n} from \"./types.js\";\n\n/** The blob_cache namespace for area summaries; the model column holds `summarizer.model`. */\nexport const COMMUNITY_SUMMARY_NAMESPACE = \"code-graph/community-summary\";\n\nfunction summaryCache(store: CodeGraphStore): CacheBlobTable {\n return new CacheBlobTable(store.db, { name: KIT.cacheBlob });\n}\n\nfunction loadSummaries(store: CodeGraphStore, model: string, hashes: readonly string[]): Map<string, string> {\n const cache = summaryCache(store);\n const found = new Map<string, string>();\n for (const contentHash of new Set(hashes)) {\n const hit = cache.get({ namespace: COMMUNITY_SUMMARY_NAMESPACE, model, contentHash });\n if (hit) found.set(contentHash, hit.value.toString(\"utf8\"));\n }\n return found;\n}\n\nfunction storeSummary(store: CodeGraphStore, model: string, contentHash: string, summary: string): void {\n summaryCache(store).put({ namespace: COMMUNITY_SUMMARY_NAMESPACE, model, contentHash }, summary);\n}\n\nfunction attachSummaries(areas: ConventionArea[], summaries: ReadonlyMap<string, string>): void {\n for (const area of areas) area.summary = summaries.get(area.contentHash);\n}\n\n/**\n * Generate or reuse the summary of every area. Only cache misses reach the\n * summarizer, so cost scales with what structurally changed, not with repo size.\n */\nexport async function summarizeConventions(\n store: CodeGraphStore,\n snapshotId: number,\n summarizer: Summarizer,\n opts?: ConventionOptions,\n): Promise<SummarizeConventionsResult> {\n const { areas, prompts, coverage } = buildConventionAreas(store, snapshotId, opts);\n attachSummaries(areas, loadSummaries(store, summarizer.model, areas.map((a) => a.contentHash)));\n let newlySummarized = 0;\n for (const area of areas) {\n if (area.summary !== undefined) continue;\n const summary = (await summarizer.summarize(prompts.get(area.contentHash)!)).trim();\n storeSummary(store, summarizer.model, area.contentHash, summary);\n area.summary = summary;\n newlySummarized++;\n }\n coverage.summarized = areas.filter((a) => a.summary).length;\n return { model: summarizer.model, coverage, areas, newlySummarized, reused: areas.length - newlySummarized };\n}\n\n/** Read-only view: the partition plus whatever summaries are already stored. Never calls a summarizer. */\nexport function getConventionMap(\n store: CodeGraphStore,\n snapshotId: number,\n model: string,\n opts?: ConventionOptions,\n): ConventionMap {\n const { areas, coverage } = buildConventionAreas(store, snapshotId, opts);\n attachSummaries(areas, loadSummaries(store, model, areas.map((a) => a.contentHash)));\n coverage.summarized = areas.filter((a) => a.summary).length;\n return { model, coverage, areas };\n}\n","import type { Embedder } from \"@titan-design/embed\";\nimport { BruteForceVectorIndex, vectorRetriever } from \"@titan-design/retrieval\";\nimport { embedTextsCached } from \"../embeddings/cache.js\";\nimport { hashEmbedText } from \"../embeddings/corpus.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { getConventionMap } from \"./summaries.js\";\nimport type { ConventionArea, ConventionMatch, ConventionQueryResult, FindConventionsOptions } from \"./types.js\";\n\nconst MATCH_FILE_CAP = 5;\nconst DEFAULT_LIMIT = 3;\n\n/**\n * \"How does this repo do X?\": rank summarized areas by similarity of their\n * summary to the question. Returns candidates, not verdicts. Summary vectors\n * share the content-addressed embedding cache with the symbol layer.\n */\nexport async function findConventions(\n store: CodeGraphStore,\n snapshotId: number,\n query: string,\n embedder: Embedder,\n model: string,\n opts: FindConventionsOptions = {},\n): Promise<ConventionQueryResult> {\n const map = getConventionMap(store, snapshotId, model, opts);\n const summarized = map.areas.filter((a): a is ConventionArea & { summary: string } => Boolean(a.summary));\n if (summarized.length === 0) {\n throw new Error(`No convention summaries stored for model ${model}; run summarizeConventions first.`);\n }\n const { byHash } = await embedTextsCached(store, embedder, summarized.map((a) => a.summary));\n const index = new BruteForceVectorIndex();\n for (const area of summarized) index.add(area.id, byHash.get(hashEmbedText(area.summary))!);\n const hits = await vectorRetriever(embedder, index).retrieve(query, { limit: opts.limit ?? DEFAULT_LIMIT });\n const byId = new Map(summarized.map((a) => [a.id, a]));\n return {\n query,\n model,\n embeddingModel: embedder.model,\n coverage: map.coverage,\n matches: hits.map((h) => toMatch(byId.get(h.id)!, h.score ?? 0)),\n };\n}\n\nfunction toMatch(area: ConventionArea & { summary: string }, score: number): ConventionMatch {\n return {\n id: area.id,\n label: area.label,\n summary: area.summary,\n files: area.files.slice(0, MATCH_FILE_CAP),\n size: area.size,\n score,\n };\n}\n"],"mappings":"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","names":["path","path","fileId","step","Node","fileId","Node","SyntaxKind","SyntaxKind","Node","targetFileId","path","fs","relative","fs","Node","SyntaxKind","Node","bindingName","Node","scopeSegment","Node","SyntaxKind","fileId","symbolNodes","path","existsSync","fileId","resolve","resolveCallee","literalText","existsSync","path","path","candidates","fileId","path","path","relative","resolve","fs","getLanguageFromPath","fileId","fileId","symbolNamesByFile","RECEIVERS","walk","TERMINALS","unreachableInBlock","analyzeFunction","countReferences","ownParamNames","walk","fileId","getLanguageFromPath","fileId","getLanguageFromPath","parseFile","shouldIncludeFile","readFileSync","path","Node","Project","ScriptTarget","readFileSync","Project","ScriptTarget","Node","oneLine","fileId","resolve","comparePairs","symbolNodes","toViolation","resolve","createHash","readFile","snap","path","readFile","edgeKey","resolve","DEFAULT_MIN_CO_IMPORTS","signatureOf","path","contentHashOf","contentHashOf","CacheBlobTable","CacheBlobTable","BruteForceVectorIndex","vectorRetriever","BruteForceVectorIndex","vectorRetriever"]}
1
+ {"version":3,"sources":["../src/store.ts","../src/schema.ts","../src/rows.ts","../src/store-reads.ts","../src/prune.ts","../src/indexer.ts","../src/extractors/ts-morph-extractor.ts","../src/index-source.ts","../src/file-walk.ts","../src/extractors/file-nodes.ts","../src/extractors/ids.ts","../src/extractors/reference-weight.ts","../src/scope-path.ts","../src/declared-names.ts","../src/extractors/call-sites.ts","../src/extractors/callable-params.ts","../src/extractors/symbol-signature.ts","../src/extractors/ts-scope.ts","../src/extractors/symbol-nodes.ts","../src/extractors/dynamic-imports.ts","../src/extractors/module-resolution.ts","../src/extractors/reexport-resolve.ts","../src/extractors/ts-calls.ts","../src/extractors/python-extractor.ts","../src/extractors/python-calls.ts","../src/extractors/dispatch.ts","../src/git-renames.ts","../src/identity/lineage.ts","../src/identity/alias-chain.ts","../src/identity/store-identity.ts","../src/identity/index-aliases.ts","../src/roles.ts","../src/generated.ts","../src/role-globs.ts","../src/git-tree-source.ts","../src/git-tree-host.ts","../src/barrel-resolve.ts","../src/incremental.ts","../src/analysis/comment-lines.ts","../src/analysis/narrating-comments.ts","../src/analysis/exception-handling.ts","../src/analysis/jsx-metrics.ts","../src/cognitive-complexity.ts","../src/lcom.ts","../src/analysis/pass-through.ts","../src/symbol-metrics.ts","../src/source-metrics.ts","../src/analysis/dead-code-python.ts","../src/analysis/dead-code.ts","../src/analysis/growth-risk.ts","../src/reconstruct.ts","../src/reuse-delta.ts","../src/metrics.ts","../src/analysis/call-metrics.ts","../src/history-metrics.ts","../src/index-metrics.ts","../src/merge.ts","../src/symbol-aliases.ts","../src/index.ts","../src/extractors/deep-ast.ts","../src/aliases.ts","../src/analysis/coverage.ts","../src/analysis/context/minify.ts","../src/analysis/relevance.ts","../src/analysis/context/signature-tree.ts","../src/analysis/context/dossier.ts","../src/analysis/context/format.ts","../src/analysis/context/bundle.ts","../src/analysis/snapshot.ts","../src/analysis/dashboard-symbol-coupling.ts","../src/read.ts","../src/catalogue/entries.ts","../src/catalogue/describe.ts","../src/check/context.ts","../src/check/rule-helpers.ts","../src/check/import-rules.ts","../src/check/violation-location.ts","../src/check/outlier-rule.ts","../src/check/metric-rules.ts","../src/check/rules.ts","../src/check/check.ts","../src/check/findings.ts","../src/check/finding-store.ts","../src/check/validate.ts","../src/check/run.ts","../src/diff/diff.ts","../src/diff/check-diff.ts","../src/diff/footprint.ts","../src/diff/footprint-diff.ts","../src/diff/gate.ts","../src/embeddings/corpus.ts","../src/embeddings/cache.ts","../src/embeddings/embeddings.ts","../src/conventions/communities.ts","../src/conventions/areas.ts","../src/conventions/summaries.ts","../src/conventions/query.ts"],"sourcesContent":["import { openDatabase, quoteIdent, runMigrations, type Db } from \"@titan-design/store-sqlite\";\nimport { MIGRATIONS, SCHEMA_VERSION, SNAPSHOT_SCOPED_TABLES } from \"./schema.js\";\nimport {\n prepareTargetedStatements,\n readEdgesTouching,\n readMetricAggregates,\n readMetricNames,\n readMetricsForNode,\n readTopByMetric,\n type MetricAggregate,\n type TargetedStatements,\n type TopMetricRow,\n} from \"./store-reads.js\";\nimport {\n rowToAlias,\n rowToEdge,\n rowToFingerprint,\n rowToMetric,\n rowToNode,\n rowToSnapshot,\n type AliasDbRow,\n type EdgeDbRow,\n type FingerprintDbRow,\n type MetricDbRow,\n type NodeDbRow,\n type SnapshotDbRow,\n} from \"./rows.js\";\nimport type {\n FileFingerprint,\n GraphEdge,\n GraphMetric,\n GraphNode,\n IdAlias,\n SnapshotRow,\n} from \"./types.js\";\n\nexport interface SnapshotInsert {\n ref: string;\n commitHash?: string;\n indexVersion: string;\n attrs?: Record<string, unknown>;\n}\n\nconst NODE_COLS = \"id, kind, name, parent_id, language, role, attrs\";\n\n/** Per-symbol `references` and `calls` edges sit below the file-level graph the default reads return. */\nfunction isStructuralLayer(edge: GraphEdge): boolean {\n return edge.kind !== \"references\" && edge.kind !== \"calls\";\n}\n\n/**\n * The code graph's query surface over store-sqlite's snapshot-scoped kit tables\n * plus this package's domain tables. Replaces codewatch's `GraphDatabase`: the\n * connection, pragmas, and migration runner are the kit's; what is left here is\n * the code-specific statements the indexer and its readers need.\n */\nexport class CodeGraphStore {\n private readonly statements;\n private readonly targeted: TargetedStatements;\n\n constructor(readonly db: Db) {\n this.statements = prepareStatements(db);\n this.targeted = prepareTargetedStatements(db);\n }\n\n createSnapshot(input: SnapshotInsert): number {\n const result = this.statements.insertSnapshot.run({\n ref: input.ref,\n commitHash: input.commitHash ?? null,\n indexVersion: input.indexVersion,\n attrs: JSON.stringify(input.attrs ?? {}),\n });\n return Number(result.lastInsertRowid);\n }\n\n /**\n * Run `write` in one transaction so a reader on another connection sees a new\n * snapshot only once every row written for it is committed, never a snapshot\n * row whose nodes or edges are still being inserted. The per-table inserts\n * nest as savepoints inside it.\n */\n atomically<T>(write: () => T): T {\n return this.db.transaction(write)();\n }\n\n insertNodes(snapshotId: number, nodes: readonly GraphNode[]): void {\n const stmt = this.statements.insertNode;\n this.db.transaction(() => {\n for (const n of nodes) {\n stmt.run({\n snapshotId,\n id: n.id,\n kind: n.kind,\n name: n.name,\n parentId: n.parentId ?? null,\n language: n.language ?? null,\n role: n.role ?? null,\n attrs: JSON.stringify(n.attrs ?? {}),\n });\n }\n })();\n }\n\n insertEdges(snapshotId: number, edges: readonly GraphEdge[]): void {\n const stmt = this.statements.insertEdge;\n this.db.transaction(() => {\n for (const e of edges) {\n stmt.run({\n snapshotId,\n srcId: e.srcId,\n dstId: e.dstId,\n kind: e.kind,\n attrs: JSON.stringify(e.attrs ?? {}),\n });\n }\n })();\n }\n\n insertMetrics(snapshotId: number, metrics: readonly GraphMetric[]): void {\n const stmt = this.statements.insertMetric;\n this.db.transaction(() => {\n for (const m of metrics) {\n stmt.run({ snapshotId, nodeId: m.nodeId, name: m.name, value: m.value, unit: m.unit ?? null });\n }\n })();\n }\n\n /**\n * Replace every metric of one `name` for a snapshot in a single transaction —\n * for an overlay such as coverage, which is re-ingested wholesale and must not\n * accumulate stale rows across runs.\n */\n replaceMetricsByName(snapshotId: number, name: string, metrics: readonly GraphMetric[]): void {\n const del = this.statements.deleteMetricsByName;\n const insert = this.statements.insertMetric;\n this.db.transaction(() => {\n del.run(snapshotId, name);\n for (const m of metrics) {\n insert.run({ snapshotId, nodeId: m.nodeId, name: m.name, value: m.value, unit: m.unit ?? null });\n }\n })();\n }\n\n insertAliases(snapshotId: number, aliases: readonly IdAlias[]): void {\n const stmt = this.statements.insertAlias;\n this.db.transaction(() => {\n for (const a of aliases) {\n stmt.run({ snapshotId, oldId: a.oldId, newId: a.newId, reason: a.reason });\n }\n })();\n }\n\n insertFingerprints(snapshotId: number, fingerprints: readonly FileFingerprint[]): void {\n const stmt = this.statements.insertFingerprint;\n this.db.transaction(() => {\n for (const f of fingerprints) {\n stmt.run({\n snapshotId,\n fileId: f.fileId,\n contentHash: f.contentHash,\n structuralHash: f.structuralHash ?? null,\n });\n }\n })();\n }\n\n getSnapshot(id: number): SnapshotRow | null {\n const row = this.statements.getSnapshot.get(id) as SnapshotDbRow | undefined;\n return row ? rowToSnapshot(row) : null;\n }\n\n listSnapshots(opts: { ref?: string; limit?: number } = {}): SnapshotRow[] {\n const limit = opts.limit ?? 50;\n const rows = (\n opts.ref\n ? this.statements.listSnapshotsByRef.all(opts.ref, limit)\n : this.statements.listSnapshots.all(limit)\n ) as SnapshotDbRow[];\n return rows.map(rowToSnapshot);\n }\n\n getLatestSnapshotByRef(ref: string): SnapshotRow | null {\n return this.listSnapshots({ ref, limit: 1 })[0] ?? null;\n }\n\n getNode(snapshotId: number, id: string): GraphNode | null {\n const row = this.statements.getNode.get(snapshotId, id) as NodeDbRow | undefined;\n return row ? rowToNode(row) : null;\n }\n\n /**\n * File-level structural graph by default: the per-symbol layer is excluded so\n * consumers that reason about module structure see the graph they expect. Pass\n * `includeSymbols` for the symbol layer (the reuse basis needs it).\n */\n listNodes(snapshotId: number, opts?: { includeSymbols?: boolean }): GraphNode[] {\n const nodes = (this.statements.listNodes.all(snapshotId) as NodeDbRow[]).map(rowToNode);\n return opts?.includeSymbols ? nodes : nodes.filter((n) => n.kind !== \"symbol\");\n }\n\n /** See {@link listNodes}: `references` and `calls` edges are the symbol layer, excluded by default. */\n listEdges(snapshotId: number, opts?: { includeReferences?: boolean }): GraphEdge[] {\n const edges = (this.statements.listEdges.all(snapshotId) as EdgeDbRow[]).map(rowToEdge);\n return opts?.includeReferences ? edges : edges.filter(isStructuralLayer);\n }\n\n listMetrics(snapshotId: number): GraphMetric[] {\n return (this.statements.listMetrics.all(snapshotId) as MetricDbRow[]).map(rowToMetric);\n }\n\n /** Every metric on one node, from the primary key instead of a whole-snapshot read. */\n listMetricsForNode(snapshotId: number, nodeId: string): GraphMetric[] {\n return readMetricsForNode(this.targeted, snapshotId, nodeId);\n }\n\n /** Distinct metric names stored for a snapshot, ascending. */\n listMetricNames(snapshotId: number): string[] {\n return readMetricNames(this.targeted, snapshotId);\n }\n\n /** The highest-valued nodes for one metric, descending; `limit` defaults to 20. */\n topByMetric(opts: { snapshotId: number; metric: string; limit?: number; kind?: string }): TopMetricRow[] {\n return readTopByMetric(this.targeted, opts);\n }\n\n /** Edges into or out of one node; symbol-layer edges are excluded unless asked, as in {@link listEdges}. */\n listEdgesTouching(snapshotId: number, nodeId: string, opts?: { includeReferences?: boolean }): GraphEdge[] {\n const edges = readEdgesTouching(this.targeted, snapshotId, nodeId);\n return opts?.includeReferences ? edges : edges.filter(isStructuralLayer);\n }\n\n /** Count, sum, min, and max per metric name and node kind; pass `name` for one metric. */\n aggregateMetrics(snapshotId: number, opts?: { name?: string }): MetricAggregate[] {\n return readMetricAggregates(this.targeted, snapshotId, opts?.name);\n }\n\n listAliases(snapshotId: number): IdAlias[] {\n return (this.statements.listAliases.all(snapshotId) as AliasDbRow[]).map(rowToAlias);\n }\n\n listFingerprints(snapshotId: number): FileFingerprint[] {\n return (this.statements.listFingerprints.all(snapshotId) as FingerprintDbRow[]).map(rowToFingerprint);\n }\n\n /** Drop whole snapshots. The domain tables carry no foreign key, so each is cleared by hand. */\n deleteSnapshots(ids: readonly number[]): void {\n if (ids.length === 0) return;\n this.db.transaction(() => {\n for (const id of ids) {\n for (const stmt of this.statements.deleteBySnapshot) stmt.run(id);\n }\n })();\n }\n\n vacuum(): void {\n this.db.exec(\"VACUUM\");\n }\n\n countRowsByTable(tables: readonly string[]): Record<string, number> {\n const out: Record<string, number> = {};\n for (const table of tables) {\n const row = this.db.prepare(`SELECT COUNT(*) AS n FROM ${quoteIdent(table)}`).get() as { n: number };\n out[table] = row.n;\n }\n return out;\n }\n\n close(): void {\n this.db.close();\n }\n}\n\nfunction prepareStatements(db: Db) {\n return {\n insertSnapshot: db.prepare(\n `INSERT INTO snapshot (ref, commit_hash, index_version, attrs)\n VALUES (@ref, @commitHash, @indexVersion, @attrs)`,\n ),\n insertNode: db.prepare(\n `INSERT OR REPLACE INTO node (snapshot_id, id, kind, name, parent_id, language, role, attrs)\n VALUES (@snapshotId, @id, @kind, @name, @parentId, @language, @role, @attrs)`,\n ),\n insertEdge: db.prepare(\n `INSERT OR REPLACE INTO edge (snapshot_id, src_id, dst_id, kind, attrs)\n VALUES (@snapshotId, @srcId, @dstId, @kind, @attrs)`,\n ),\n insertMetric: db.prepare(\n `INSERT OR REPLACE INTO metric (snapshot_id, node_id, name, value, unit)\n VALUES (@snapshotId, @nodeId, @name, @value, @unit)`,\n ),\n insertAlias: db.prepare(\n `INSERT OR REPLACE INTO id_alias (snapshot_id, old_id, new_id, reason)\n VALUES (@snapshotId, @oldId, @newId, @reason)`,\n ),\n insertFingerprint: db.prepare(\n `INSERT OR REPLACE INTO file_fingerprint (snapshot_id, file_id, content_hash, structural_hash)\n VALUES (@snapshotId, @fileId, @contentHash, @structuralHash)`,\n ),\n getSnapshot: db.prepare(\"SELECT * FROM snapshot WHERE id = ?\"),\n listSnapshots: db.prepare(\"SELECT * FROM snapshot ORDER BY taken_at DESC, id DESC LIMIT ?\"),\n listSnapshotsByRef: db.prepare(\n \"SELECT * FROM snapshot WHERE ref = ? ORDER BY taken_at DESC, id DESC LIMIT ?\",\n ),\n getNode: db.prepare(`SELECT ${NODE_COLS} FROM node WHERE snapshot_id = ? AND id = ?`),\n listNodes: db.prepare(`SELECT ${NODE_COLS} FROM node WHERE snapshot_id = ?`),\n listEdges: db.prepare(\"SELECT src_id, dst_id, kind, attrs FROM edge WHERE snapshot_id = ?\"),\n listMetrics: db.prepare(\"SELECT node_id, name, value, unit FROM metric WHERE snapshot_id = ?\"),\n listAliases: db.prepare(\"SELECT old_id, new_id, reason FROM id_alias WHERE snapshot_id = ?\"),\n listFingerprints: db.prepare(\n \"SELECT file_id, content_hash, structural_hash FROM file_fingerprint WHERE snapshot_id = ?\",\n ),\n deleteMetricsByName: db.prepare(\"DELETE FROM metric WHERE snapshot_id = ? AND name = ?\"),\n deleteBySnapshot: [...SNAPSHOT_SCOPED_TABLES, \"snapshot\"].map((table) =>\n db.prepare(`DELETE FROM ${quoteIdent(table)} WHERE ${table === \"snapshot\" ? \"id\" : \"snapshot_id\"} = ?`),\n ),\n };\n}\n\n/** Open (creating if absent) a code graph database and bring it to the current schema. */\nexport function openCodeGraph(dbPath: string): CodeGraphStore {\n const db = openDatabase(dbPath, { schemaVersion: SCHEMA_VERSION });\n runMigrations(db, MIGRATIONS);\n return new CodeGraphStore(db);\n}\n","import { kitMigration, type Migration } from \"@titan-design/store-sqlite\";\n\n/**\n * Kit table names. The code graph is snapshot-scoped end to end: a whole repo is\n * re-indexed together, so `snapshotTableDdl` + `entitySnapTableDdl` are the right\n * time model and the interval `edgeTableDdl` is not — one unchanged import would\n * otherwise write a row per file per snapshot. The edge table below is therefore\n * the snapshot-scoped counterpart, owned here.\n */\nexport const KIT = { snapshot: \"snapshot\", entitySnap: \"node\", cacheBlob: \"blob_cache\" } as const;\n\n/**\n * Two columns the kit's `entity_snap` shape does not carry but every consumer of\n * a code graph reads directly, plus the snapshot provenance the reuse basis\n * selects on. Kept as real columns rather than folded into `attrs` so the\n * vocabularies stay queryable and stay codewatch-compatible.\n */\nconst KIT_EXTENSIONS = `\n ALTER TABLE node ADD COLUMN language TEXT;\n ALTER TABLE node ADD COLUMN role TEXT;\n ALTER TABLE snapshot ADD COLUMN commit_hash TEXT;\n ALTER TABLE snapshot ADD COLUMN index_version TEXT NOT NULL DEFAULT '';\n`;\n\n/**\n * Domain tables. `edge` is the snapshot-scoped edge shape (the kit's own edge\n * table is bi-temporal); `metric` holds index-time measurements keyed by node;\n * `id_alias` carries a node id across a rename so two snapshots line up; and\n * `file_fingerprint` is the reuse basis the incremental indexer diffs against.\n */\nexport const DOMAIN_DDL = `\n CREATE TABLE IF NOT EXISTS edge (\n snapshot_id INTEGER NOT NULL,\n src_id TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n kind TEXT NOT NULL,\n attrs TEXT,\n PRIMARY KEY (snapshot_id, src_id, dst_id, kind)\n );\n CREATE INDEX IF NOT EXISTS idx_edge_dst ON edge(snapshot_id, dst_id);\n CREATE INDEX IF NOT EXISTS idx_edge_kind ON edge(snapshot_id, kind);\n\n CREATE TABLE IF NOT EXISTS metric (\n snapshot_id INTEGER NOT NULL,\n node_id TEXT NOT NULL,\n name TEXT NOT NULL,\n value REAL,\n unit TEXT,\n PRIMARY KEY (snapshot_id, node_id, name)\n );\n CREATE INDEX IF NOT EXISTS idx_metric_name ON metric(snapshot_id, name);\n\n CREATE TABLE IF NOT EXISTS id_alias (\n snapshot_id INTEGER NOT NULL,\n old_id TEXT NOT NULL,\n new_id TEXT NOT NULL,\n reason TEXT NOT NULL,\n PRIMARY KEY (snapshot_id, old_id, new_id)\n );\n\n CREATE TABLE IF NOT EXISTS file_fingerprint (\n snapshot_id INTEGER NOT NULL,\n file_id TEXT NOT NULL,\n content_hash TEXT NOT NULL,\n structural_hash TEXT,\n PRIMARY KEY (snapshot_id, file_id)\n );\n`;\n\n/**\n * Stored audit findings and model verdicts. `key` is a `findingKey`, not `Finding.id`,\n * because an external tool's id embeds its line number and can repeat within one audit.\n * The whole `Finding` and a verdict's citations live in `attrs`.\n */\nexport const FINDING_DDL = `\n CREATE TABLE IF NOT EXISTS finding (\n snapshot_id INTEGER NOT NULL,\n key TEXT NOT NULL,\n finding_id TEXT NOT NULL,\n tool TEXT NOT NULL,\n signal TEXT NOT NULL,\n path TEXT NOT NULL,\n line_start INTEGER,\n line_end INTEGER,\n severity TEXT NOT NULL,\n excerpt_hash TEXT,\n attrs TEXT NOT NULL,\n PRIMARY KEY (snapshot_id, key)\n );\n CREATE INDEX IF NOT EXISTS idx_finding_path ON finding(snapshot_id, path);\n\n CREATE TABLE IF NOT EXISTS verdict (\n snapshot_id INTEGER NOT NULL,\n key TEXT NOT NULL,\n verdict TEXT NOT NULL CHECK (verdict IN ('confirmed', 'justified', 'unclear')),\n rationale TEXT NOT NULL,\n excerpt_hash TEXT NOT NULL,\n model TEXT,\n run_id TEXT,\n cost_usd REAL,\n provenance TEXT,\n control_run TEXT,\n carried_from INTEGER,\n attrs TEXT NOT NULL,\n PRIMARY KEY (snapshot_id, key)\n );\n`;\n\n/** Every table keyed by `snapshot_id`. No DDL above declares a foreign key, so dropping a snapshot walks this list. */\nexport const SNAPSHOT_SCOPED_TABLES = [\n \"node\",\n \"edge\",\n \"metric\",\n \"id_alias\",\n \"file_fingerprint\",\n \"finding\",\n \"verdict\",\n] as const;\n\nexport const MIGRATIONS: Migration[] = [\n kitMigration(1, { snapshot: KIT.snapshot, entitySnap: KIT.entitySnap, cacheBlob: KIT.cacheBlob }),\n { version: 2, name: \"code graph columns\", up: (db) => db.exec(KIT_EXTENSIONS) },\n { version: 3, name: \"code graph tables\", up: (db) => db.exec(DOMAIN_DDL) },\n { version: 4, name: \"findings and verdicts\", up: (db) => db.exec(FINDING_DDL) },\n];\n\n/** The top of this package's schema. A code graph database is never shared, so this is the top of one. */\nexport const SCHEMA_VERSION = Math.max(...MIGRATIONS.map((m) => m.version));\n","import type {\n FileFingerprint,\n GraphEdge,\n GraphMetric,\n GraphNode,\n IdAlias,\n IdAliasReason,\n SnapshotRow,\n} from \"./types.js\";\n\n// Raw row shapes as stored in SQLite, paired with mappers to the domain types.\n// Kept separate from the connection/statement manager in database.ts.\n\nexport interface SnapshotDbRow {\n id: number;\n ref: string;\n commit_hash: string | null;\n taken_at: string;\n index_version: string;\n attrs: string;\n}\n\nexport interface NodeDbRow {\n id: string;\n kind: string;\n name: string;\n parent_id: string | null;\n language: string | null;\n role: string | null;\n attrs: string;\n}\n\nexport interface EdgeDbRow {\n src_id: string;\n dst_id: string;\n kind: string;\n attrs: string;\n}\n\nexport interface MetricDbRow {\n node_id: string;\n name: string;\n value: number | null;\n unit: string | null;\n}\n\nexport interface AliasDbRow {\n old_id: string;\n new_id: string;\n reason: string;\n}\n\nexport interface FingerprintDbRow {\n file_id: string;\n content_hash: string;\n structural_hash: string | null;\n}\n\nexport function rowToSnapshot(row: SnapshotDbRow): SnapshotRow {\n return {\n id: row.id,\n ref: row.ref,\n commitHash: row.commit_hash,\n takenAt: row.taken_at,\n indexVersion: row.index_version,\n attrs: JSON.parse(row.attrs) as Record<string, unknown>,\n };\n}\n\nexport function rowToNode(row: NodeDbRow): GraphNode {\n return {\n id: row.id,\n kind: row.kind as GraphNode[\"kind\"],\n name: row.name,\n parentId: row.parent_id ?? undefined,\n language: row.language ?? undefined,\n role: (row.role ?? undefined) as GraphNode[\"role\"],\n attrs: JSON.parse(row.attrs) as Record<string, unknown>,\n };\n}\n\nexport function rowToEdge(row: EdgeDbRow): GraphEdge {\n return {\n srcId: row.src_id,\n dstId: row.dst_id,\n kind: row.kind as GraphEdge[\"kind\"],\n attrs: JSON.parse(row.attrs) as Record<string, unknown>,\n };\n}\n\nexport function rowToMetric(row: MetricDbRow): GraphMetric {\n return {\n nodeId: row.node_id,\n name: row.name,\n value: row.value,\n unit: row.unit ?? undefined,\n };\n}\n\nexport function rowToAlias(row: AliasDbRow): IdAlias {\n return {\n oldId: row.old_id,\n newId: row.new_id,\n reason: row.reason as IdAliasReason,\n };\n}\n\nexport function rowToFingerprint(row: FingerprintDbRow): FileFingerprint {\n return {\n fileId: row.file_id,\n contentHash: row.content_hash,\n structuralHash: row.structural_hash ?? undefined,\n };\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport { rowToEdge, rowToMetric, type EdgeDbRow, type MetricDbRow } from \"./rows.js\";\nimport type { GraphEdge, GraphMetric, NodeKind } from \"./types.js\";\n\n/** One metric's values over the nodes of one kind in one snapshot; `count` excludes null values. */\nexport interface MetricAggregate {\n name: string;\n nodeKind: NodeKind;\n count: number;\n sum: number | null;\n min: number | null;\n max: number | null;\n}\n\ninterface AggregateDbRow {\n name: string;\n node_kind: string;\n count: number;\n sum: number | null;\n min: number | null;\n max: number | null;\n}\n\ninterface AllStatement<P extends unknown[]> {\n readonly source: string;\n all(...params: P): unknown[];\n}\n\n/** One node's value for one metric, joined to the node's own vocabulary columns. */\nexport interface TopMetricRow {\n nodeId: string;\n name: string;\n kind: string;\n role: string | null;\n value: number | null;\n unit: string | null;\n}\n\ninterface TopMetricDbRow {\n node_id: string;\n value: number | null;\n unit: string | null;\n kind: string;\n name: string;\n role: string | null;\n}\n\nexport interface TargetedStatements {\n listMetricsForNode: AllStatement<[snapshotId: number, nodeId: string]>;\n listEdgesTouching: AllStatement<[{ snapshotId: number; nodeId: string }]>;\n aggregateMetric: AllStatement<[snapshotId: number, name: string]>;\n aggregateMetrics: AllStatement<[snapshotId: number]>;\n listMetricNames: AllStatement<[snapshotId: number]>;\n topByMetric: AllStatement<[snapshotId: number, metric: string, limit: number]>;\n topByMetricOfKind: AllStatement<[snapshotId: number, metric: string, kind: string, limit: number]>;\n}\n\nconst EDGE_COLS = \"src_id, dst_id, kind, attrs\";\n// CROSS JOIN pins metric as the outer loop; unanalyzed, SQLite otherwise probes metric once per node.\nconst AGGREGATE_SELECT = `SELECT m.name AS name, n.kind AS node_kind, COUNT(m.value) AS count,\n SUM(m.value) AS sum, MIN(m.value) AS min, MAX(m.value) AS max\n FROM metric m CROSS JOIN node n ON n.snapshot_id = m.snapshot_id AND n.id = m.node_id`;\nconst TOP_SELECT = `SELECT m.node_id, m.value, m.unit, n.kind, n.name, n.role\n FROM metric m JOIN node n ON n.snapshot_id = m.snapshot_id AND n.id = m.node_id\n WHERE m.snapshot_id = ? AND m.name = ?`;\nconst TOP_ORDER = \"ORDER BY m.value DESC LIMIT ?\";\n\n/** Reads that touch one node or one metric instead of a whole snapshot; each is an index search. */\nexport function prepareTargetedStatements(db: Db): TargetedStatements {\n return {\n listMetricsForNode: db.prepare(\n \"SELECT node_id, name, value, unit FROM metric WHERE snapshot_id = ? AND node_id = ?\",\n ),\n // The second arm skips self-loops so an edge from a node to itself comes back once.\n listEdgesTouching: db.prepare(\n `SELECT ${EDGE_COLS} FROM edge WHERE snapshot_id = @snapshotId AND src_id = @nodeId\n UNION ALL\n SELECT ${EDGE_COLS} FROM edge WHERE snapshot_id = @snapshotId AND dst_id = @nodeId AND src_id <> @nodeId`,\n ),\n aggregateMetric: db.prepare(\n `${AGGREGATE_SELECT} WHERE m.snapshot_id = ? AND m.name = ? GROUP BY n.kind ORDER BY n.kind`,\n ),\n aggregateMetrics: db.prepare(\n `${AGGREGATE_SELECT} WHERE m.snapshot_id = ? GROUP BY m.name, n.kind ORDER BY m.name, n.kind`,\n ),\n listMetricNames: db.prepare(\"SELECT DISTINCT name FROM metric WHERE snapshot_id = ? ORDER BY name\"),\n topByMetric: db.prepare(`${TOP_SELECT} ${TOP_ORDER}`),\n topByMetricOfKind: db.prepare(`${TOP_SELECT} AND n.kind = ? ${TOP_ORDER}`),\n };\n}\n\nexport function readMetricsForNode(stmts: TargetedStatements, snapshotId: number, nodeId: string): GraphMetric[] {\n return (stmts.listMetricsForNode.all(snapshotId, nodeId) as MetricDbRow[]).map(rowToMetric);\n}\n\nexport function readEdgesTouching(stmts: TargetedStatements, snapshotId: number, nodeId: string): GraphEdge[] {\n return (stmts.listEdgesTouching.all({ snapshotId, nodeId }) as EdgeDbRow[]).map(rowToEdge);\n}\n\nexport function readMetricNames(stmts: TargetedStatements, snapshotId: number): string[] {\n return (stmts.listMetricNames.all(snapshotId) as Array<{ name: string }>).map((r) => r.name);\n}\n\nexport function readTopByMetric(\n stmts: TargetedStatements,\n opts: { snapshotId: number; metric: string; limit?: number; kind?: string },\n): TopMetricRow[] {\n const limit = opts.limit ?? 20;\n const rows = (\n opts.kind === undefined\n ? stmts.topByMetric.all(opts.snapshotId, opts.metric, limit)\n : stmts.topByMetricOfKind.all(opts.snapshotId, opts.metric, opts.kind, limit)\n ) as TopMetricDbRow[];\n return rows.map((r) => ({\n nodeId: r.node_id,\n name: r.name,\n kind: r.kind,\n role: r.role,\n value: r.value,\n unit: r.unit,\n }));\n}\n\nexport function readMetricAggregates(stmts: TargetedStatements, snapshotId: number, name?: string): MetricAggregate[] {\n const rows = (\n name === undefined ? stmts.aggregateMetrics.all(snapshotId) : stmts.aggregateMetric.all(snapshotId, name)\n ) as AggregateDbRow[];\n return rows.map((r) => ({\n name: r.name,\n nodeKind: r.node_kind as NodeKind,\n count: r.count,\n sum: r.sum,\n min: r.min,\n max: r.max,\n }));\n}\n","import { SNAPSHOT_SCOPED_TABLES } from \"./schema.js\";\nimport type { CodeGraphStore } from \"./store.js\";\nimport type { SnapshotRow } from \"./types.js\";\n\nexport interface PrunePlan {\n keep: SnapshotRow[];\n remove: SnapshotRow[];\n}\n\nexport interface PruneOptions {\n keep?: number;\n keepRefs?: readonly string[];\n}\n\n// codewatch's list named `boundary` and `entry_point`, which this schema never created.\nconst CASCADE_TABLES = SNAPSHOT_SCOPED_TABLES;\n\nexport function planPrune(store: CodeGraphStore, options: PruneOptions = {}): PrunePlan {\n const keepCount = options.keep ?? 10;\n const keepRefs = new Set(options.keepRefs ?? []);\n const all = store.listSnapshots({ limit: 1_000_000 });\n const keep: SnapshotRow[] = [];\n const remove: SnapshotRow[] = [];\n for (let i = 0; i < all.length; i++) {\n const snap = all[i]!;\n if (i < keepCount || keepRefs.has(snap.ref)) {\n keep.push(snap);\n } else {\n remove.push(snap);\n }\n }\n return { keep, remove };\n}\n\nexport interface PruneResult {\n plan: PrunePlan;\n rowsBefore: Record<string, number>;\n rowsAfter: Record<string, number>;\n vacuumed: boolean;\n}\n\nexport function runPrune(store: CodeGraphStore, options: PruneOptions & { vacuum?: boolean } = {}): PruneResult {\n const plan = planPrune(store, options);\n const tables = [\"snapshot\", ...CASCADE_TABLES];\n const rowsBefore = store.countRowsByTable(tables);\n store.deleteSnapshots(plan.remove.map((s) => s.id));\n if (options.vacuum) store.vacuum();\n const rowsAfter = store.countRowsByTable(tables);\n return { plan, rowsBefore, rowsAfter, vacuumed: !!options.vacuum };\n}\n","import { realpathSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { parseFile, type ParsedFile } from \"@titan-design/code-parser\";\nimport type { CodeGraphStore } from \"./store.js\";\nimport { LanguageExtractor } from \"./extractors/dispatch.js\";\nimport { detectGitHead, detectGitToplevel } from \"./git-renames.js\";\nimport { computeAliasBridge } from \"./identity/index-aliases.js\";\nimport { ALIAS_BASE_ATTR } from \"./identity/lineage.js\";\nimport { annotateRoles, computeRoleHints } from \"./roles.js\";\nimport { workingTreeSource, type IndexSource } from \"./index-source.js\";\nimport { rootsAtRevision } from \"./git-tree-source.js\";\nimport { pruneDanglingReferences } from \"./barrel-resolve.js\";\nimport { fileId } from \"./extractors/ids.js\";\nimport {\n assembleFragments,\n buildFingerprints,\n classifyForReuse,\n classifyParsed,\n loadReuseBasis,\n readSourceFiles,\n} from \"./incremental.js\";\nimport { computeDeltaAffected } from \"./reuse-delta.js\";\nimport { buildIndexerMetrics } from \"./index-metrics.js\";\nimport type { HistoryMetricsOptions } from \"./history-metrics.js\";\nimport { mergeFragments, type ExtractAccumulator } from \"./merge.js\";\nimport { predatesQualifiedSymbols, qualifiedSymbolAliases } from \"./symbol-aliases.js\";\nimport type { GraphMetric, IdAlias } from \"./types.js\";\n\n/**\n * Bumping this invalidates every reuse basis: a snapshot written by a different\n * index version is never reused, so a change to node/edge shape or to a metric's\n * value for the same bytes can never be carried forward from an incompatible graph.\n */\nexport const INDEX_VERSION = \"0.22.0\";\n\n/** The languages walked and extracted. `typescript` covers `.ts` and `.tsx`. */\nconst LANGUAGES = [\"typescript\", \"python\"] as const;\n\nexport interface IndexOptions {\n /** Roots to walk. Node ids are still rooted at the git toplevel, so importers across roots share an id space. */\n paths: string[];\n ref?: string;\n commitHash?: string;\n tsConfig?: string;\n detectRenames?: boolean;\n computeMetrics?: boolean;\n /**\n * Reuse the prior snapshot for byte-identical files: skip their tree-sitter\n * parse + ts-morph extract and carry their nodes/edges/source metrics forward.\n * Defaults to `true`; the reuse path is equivalent to a full index, so the only\n * reason to disable it is to rebuild from scratch.\n */\n incremental?: boolean;\n /** Git churn, recency, and ownership metrics. Defaults to `true`; history is skipped silently outside git. */\n computeChurn?: boolean;\n /** Primary churn window in days (default 30); scopes ownership. */\n churnWindowDays?: number;\n /** Windows to store churn for (default 30, 90, 180); the primary window is always included. */\n churnWindows?: number[];\n /** Also store an all-time `lifetime` churn and ownership window over full git history. */\n lifetime?: boolean;\n /** Where files are listed and read from. Defaults to {@link workingTreeSource}. */\n source?: IndexSource;\n}\n\nexport interface IndexResult {\n snapshotId: number;\n files: number;\n nodes: number;\n edges: number;\n aliases: number;\n metrics: number;\n /** Files whose parse + extract were skipped by reusing the prior snapshot. */\n reused: number;\n /** Files parsed + extracted this run (new, changed, or full index). */\n reparsed: number;\n /** Parsed files whose extract was skipped as cosmetic; a subset of `reparsed`. */\n cosmetic: number;\n nodesByKind: Record<string, number>;\n edgesByKind: Record<string, number>;\n}\n\nfunction canonicalizePath(p: string): string {\n try {\n return realpathSync(p);\n } catch {\n return p;\n }\n}\n\nfunction normalizePaths(paths: readonly string[]): string[] {\n if (paths.length === 0) throw new Error(\"indexPaths requires at least one path\");\n return [...new Set(paths.map((p) => path.resolve(p)))];\n}\n\nfunction countByKind<T extends { kind: string }>(items: Iterable<T>): Record<string, number> {\n const out: Record<string, number> = {};\n for (const item of items) out[item.kind] = (out[item.kind] ?? 0) + 1;\n return out;\n}\n\nfunction persist(\n store: CodeGraphStore,\n snapshot: { ref: string; commitHash?: string; aliasBase: number | null },\n accumulator: ExtractAccumulator,\n aliases: readonly IdAlias[],\n metrics: readonly GraphMetric[],\n): number {\n const { ref, commitHash, aliasBase } = snapshot;\n const attrs = { [ALIAS_BASE_ATTR]: aliasBase };\n const snapshotId = store.createSnapshot({ ref, commitHash, indexVersion: INDEX_VERSION, attrs });\n store.insertNodes(snapshotId, [...accumulator.nodes.values()]);\n store.insertEdges(snapshotId, [...accumulator.edges.values()]);\n if (aliases.length > 0) store.insertAliases(snapshotId, aliases);\n if (metrics.length > 0) store.insertMetrics(snapshotId, metrics);\n return snapshotId;\n}\n\n/** Aliases from bare-name symbol ids to qualified ones, when the newest prior snapshot predates them. */\nfunction resolveSymbolAliases(\n store: CodeGraphStore,\n idRoot: string,\n parsedByPath: ReadonlyMap<string, ParsedFile>,\n nodeIds: ReadonlySet<string>,\n): IdAlias[] {\n const prior = store.listSnapshots({ limit: 1 })[0];\n if (!prior || !predatesQualifiedSymbols(prior.indexVersion)) return [];\n const files = [...parsedByPath.values()].map((file) => ({ fileId: fileId(idRoot, file.filePath), file }));\n return qualifiedSymbolAliases(files, nodeIds);\n}\n\n/**\n * Node ids are rooted at the git toplevel so a subtree index shares an id space\n * with a whole-repo one. Inside git, roots are canonicalized to match\n * `git rev-parse --show-toplevel`, which resolves symlinks (`/var` →\n * `/private/var` on macOS); outside git they are left as the caller wrote them.\n * A revision source roots ids at its own repo root instead.\n */\nfunction resolveRoots(paths: readonly string[], source: IndexSource): { rootDirs: string[]; idRoot: string } {\n const raw = normalizePaths(paths);\n if (source.revision) return rootsAtRevision(raw, source.revision);\n const gitToplevel = detectGitToplevel(raw[0]!);\n const rootDirs = gitToplevel !== null ? raw.map(canonicalizePath) : raw;\n return { rootDirs, idRoot: gitToplevel ?? rootDirs[0]! };\n}\n\nasync function parseAll(\n toParse: readonly { filePath: string; content: string; language: string }[],\n): Promise<Map<string, ParsedFile>> {\n const parsed = new Map<string, ParsedFile>();\n for (const rf of toParse) {\n parsed.set(rf.filePath, await parseFile(rf.content, rf.filePath, rf.language));\n }\n return parsed;\n}\n\n/** A revision's history ends at its commit, so its windows end at the commit's time, not the wall clock. */\nfunction historyOptions(options: IndexOptions, source: IndexSource): HistoryMetricsOptions {\n return {\n churnWindowDays: options.churnWindowDays,\n churnWindows: options.churnWindows,\n includeLifetime: options.lifetime === true,\n rev: source.revision?.commit,\n nowEpoch: source.revision?.commitEpoch,\n };\n}\n\n/**\n * Index one or more roots into a new snapshot: walk, read, parse what changed,\n * extract, annotate roles, compute metrics, and persist. Files unchanged since\n * the prior snapshot are carried forward rather than re-parsed, so the result\n * matches a full index regardless of how much was reused.\n */\nexport async function indexPaths(store: CodeGraphStore, options: IndexOptions): Promise<IndexResult> {\n const source = options.source ?? workingTreeSource();\n const { rootDirs, idRoot } = resolveRoots(options.paths, source);\n const readFiles = await readSourceFiles(await source.listFiles(rootDirs, LANGUAGES), source);\n\n const reuse = options.incremental !== false ? loadReuseBasis(store, INDEX_VERSION) : null;\n const currentFileIds = new Set(readFiles.map((rf) => fileId(idRoot, rf.filePath)));\n // On a file-membership delta, reuse every unchanged file except those whose\n // imports the delta re-resolves; empty when membership is unchanged.\n const affected = reuse ? computeDeltaAffected(reuse, currentFileIds) : new Set<string>();\n const { toParse, reusedFileIds } = classifyForReuse(readFiles, idRoot, reuse, affected);\n\n const parsedByPath = await parseAll(toParse);\n const classified = classifyParsed(parsedByPath, idRoot, reuse, reusedFileIds, affected);\n const accumulator = mergeFragments(\n assembleFragments({\n readFiles,\n idRoot,\n parsedByPath,\n reuse,\n cosmeticFileIds: classified.cosmeticFileIds,\n extractor: new LanguageExtractor({ repoRoot: idRoot, tsConfigPath: options.tsConfig, source }),\n }),\n );\n const roleHints = computeRoleHints(readFiles, idRoot, fileId, source);\n const annotated = annotateRoles([...accumulator.nodes.values()], roleHints);\n accumulator.nodes = new Map(annotated.map((n) => [n.id, n]));\n pruneDanglingReferences(accumulator.nodes, accumulator.edges);\n\n const metrics =\n options.computeMetrics === false\n ? []\n : buildIndexerMetrics({\n nodes: accumulator.nodes,\n edges: accumulator.edges,\n parsedFiles: [...parsedByPath.values()],\n reusedSourceMetrics: reuse\n ? reusedFileIds.flatMap((id) => reuse.sourceMetricsByFile.get(id) ?? [])\n : [],\n idRoot,\n history: options.computeChurn === false ? undefined : historyOptions(options, source),\n });\n\n // A revision's indexed dirs may be gone from disk, so its git calls run at the repo root.\n const rootDir = source.revision ? idRoot : rootDirs[0]!;\n const ref = options.ref ?? \"wd\";\n const commitHash = options.commitHash ?? source.revision?.commit ?? detectGitHead(rootDir) ?? undefined;\n const bridge = computeAliasBridge(store, { ...options, rootDir, idRoot, ref, commitHash, nodes: accumulator.nodes });\n const aliases = [\n ...bridge.aliases,\n ...resolveSymbolAliases(store, idRoot, parsedByPath, new Set(accumulator.nodes.keys())),\n ];\n const snapshot = { ref, commitHash, aliasBase: bridge.baseSnapshotId };\n const fingerprints = buildFingerprints(readFiles, idRoot, classified.structuralByFileId);\n const snapshotId = store.atomically(() => {\n const id = persist(store, snapshot, accumulator, aliases, metrics);\n store.insertFingerprints(id, fingerprints);\n return id;\n });\n\n return {\n snapshotId,\n files: readFiles.length,\n nodes: accumulator.nodes.size,\n edges: accumulator.edges.size,\n aliases: aliases.length,\n metrics: metrics.length,\n reused: reusedFileIds.length,\n reparsed: toParse.length,\n cosmetic: classified.cosmeticFileIds.size,\n nodesByKind: countByKind(accumulator.nodes.values()),\n edgesByKind: countByKind(accumulator.edges.values()),\n };\n}\n","import {\n Project,\n ScriptTarget,\n ModuleKind,\n ModuleResolutionKind,\n type ExportDeclaration,\n type ImportDeclaration,\n type SourceFile,\n} from \"ts-morph\";\nimport type { Extractor, ParsedFile } from \"@titan-design/code-parser\";\nimport type { GraphEdge, GraphFragment, GraphNode } from \"../types.js\";\nimport { workingTreeSource, type IndexSource } from \"../index-source.js\";\nimport { buildFileModuleNodes } from \"./file-nodes.js\";\nimport { externalId, fileId, symbolId } from \"./ids.js\";\nimport {\n addWeightedEdge,\n bindingWeight,\n buildLocalUsageCounts,\n importWeight,\n namedImportBindings,\n reExportWeight,\n} from \"./reference-weight.js\";\nimport { buildSymbolNodes } from \"./symbol-nodes.js\";\nimport {\n dynamicImportSpecifiers,\n recordDynamicSymbolRefEdges,\n} from \"./dynamic-imports.js\";\nimport { resolveReExportOrigin } from \"./reexport-resolve.js\";\nimport {\n inRepoFileId,\n isRelativeSpecifier,\n remapDistToSrc,\n repoTypeRoots,\n resolveRelativeAbs,\n} from \"./module-resolution.js\";\nimport { collectTsCallEdges } from \"./ts-calls.js\";\n\n/** Mutable accumulator threaded through one file's edge collection. */\ninterface EdgeCollector {\n srcAbs: string;\n srcFileId: string;\n usage: Map<string, number>;\n agg: Map<string, GraphEdge>;\n externalNodes: GraphNode[];\n seenExternals: Set<string>;\n}\n\nexport interface TsMorphGraphExtractorOptions {\n repoRoot: string;\n tsConfigPath?: string;\n project?: Project;\n source?: IndexSource;\n}\n\nconst RETIRE_BATCH = 100;\n\nexport class TsMorphGraphExtractor implements Extractor<GraphFragment> {\n readonly name = \"ts-morph-graph\";\n private readonly repoRoot: string;\n private readonly tsConfigPath?: string;\n private project?: Project;\n private readonly ownsProject: boolean;\n private readonly source: IndexSource;\n private readonly retired: SourceFile[] = [];\n private readonly fileExists = (abs: string): boolean => this.source.fileExists(abs);\n\n constructor(options: TsMorphGraphExtractorOptions) {\n this.repoRoot = options.repoRoot;\n this.tsConfigPath = options.tsConfigPath;\n this.project = options.project;\n this.ownsProject = options.project === undefined;\n this.source = options.source ?? workingTreeSource();\n }\n\n extract(file: ParsedFile): GraphFragment[] {\n if (!isTypeScriptFile(file)) return [];\n\n const project = this.ensureProject();\n const sourceFile = this.loadSourceFile(project, file);\n try {\n return this.extractFrom(sourceFile, file);\n } finally {\n if (this.ownsProject) this.retire(project, sourceFile);\n }\n }\n\n private retire(project: Project, sourceFile: SourceFile): void {\n this.retired.push(sourceFile);\n if (this.retired.length < RETIRE_BATCH) return;\n for (const sf of this.retired.splice(0)) project.removeSourceFile(sf);\n }\n\n private extractFrom(sourceFile: SourceFile, file: ParsedFile): GraphFragment[] {\n const nodes = this.buildFileAndModuleNodes(sourceFile);\n const symbolNodes = buildSymbolNodes(this.repoRoot, sourceFile, file);\n const { edges, externalNodes } = this.collectEdges(sourceFile);\n const calls = collectTsCallEdges(sourceFile, {\n repoRoot: this.repoRoot,\n srcFileId: fileId(this.repoRoot, sourceFile.getFilePath()),\n localSymbols: new Set(symbolNodes.map((n) => n.name)),\n fileExists: this.fileExists,\n });\n return [{ nodes: [...nodes, ...symbolNodes, ...externalNodes], edges: [...edges, ...calls] }];\n }\n\n private ensureProject(): Project {\n if (this.project) return this.project;\n const fileSystem = this.source.fileSystem;\n this.project = this.tsConfigPath\n ? new Project({ tsConfigFilePath: this.tsConfigPath, fileSystem })\n : new Project({\n fileSystem,\n compilerOptions: {\n allowJs: true,\n target: ScriptTarget.ESNext,\n module: ModuleKind.ESNext,\n moduleResolution: ModuleResolutionKind.NodeNext,\n typeRoots: repoTypeRoots(this.repoRoot),\n },\n });\n return this.project;\n }\n\n private loadSourceFile(project: Project, file: ParsedFile): SourceFile {\n const existing = project.getSourceFile(file.filePath);\n if (existing) {\n if (existing.getFullText() !== file.content) {\n existing.replaceWithText(file.content);\n }\n return existing;\n }\n return project.createSourceFile(file.filePath, file.content, {\n overwrite: true,\n });\n }\n\n private buildFileAndModuleNodes(sourceFile: SourceFile): GraphNode[] {\n return buildFileModuleNodes(this.repoRoot, sourceFile.getFilePath());\n }\n\n private collectEdges(sourceFile: SourceFile): {\n edges: GraphEdge[];\n externalNodes: GraphNode[];\n } {\n const c: EdgeCollector = {\n srcAbs: sourceFile.getFilePath(),\n srcFileId: fileId(this.repoRoot, sourceFile.getFilePath()),\n usage: buildLocalUsageCounts(sourceFile),\n agg: new Map(),\n externalNodes: [],\n seenExternals: new Set(),\n };\n for (const decl of sourceFile.getImportDeclarations()) {\n this.recordImportEdge(c, decl);\n }\n for (const decl of sourceFile.getExportDeclarations()) {\n this.recordReExportEdge(c, decl);\n }\n for (const specifier of dynamicImportSpecifiers(sourceFile)) {\n const dstId = this.resolveRelativeInternal(c.srcAbs, specifier);\n if (dstId) addWeightedEdge(c.agg, c.srcFileId, dstId, \"imports\", specifier, 1);\n }\n // C-68: destructured dynamic imports (`const { x } = await import(...)`) also\n // credit the target symbol; resolution is delegated so this stays out of the\n // (churn-hot, LOC-bound) extractor body.\n recordDynamicSymbolRefEdges(sourceFile, c.srcFileId, c.agg, (s) =>\n this.resolveRelativeInternal(c.srcAbs, s),\n );\n return { edges: [...c.agg.values()], externalNodes: c.externalNodes };\n }\n\n private recordImportEdge(c: EdgeCollector, decl: ImportDeclaration): void {\n const specifier = decl.getModuleSpecifierValue();\n const dstId = this.resolveTarget(c, specifier, decl);\n if (dstId) {\n addWeightedEdge(c.agg, c.srcFileId, dstId, \"imports\", specifier, importWeight(decl, c.usage));\n }\n this.recordSymbolReferences(c, decl);\n }\n\n /**\n * Split an import into per-export `references` edges targeting `symbol` nodes,\n * so per-symbol utilization (which exports are hot) falls out of the same\n * inbound-weight sum that powers file utilization (C-53). Extracted *forward*\n * from the importing file — source-local, exactly like the file-level import\n * weight — which sidesteps the reuse-breaking reverse `findReferences` query:\n * an unchanged file's outbound reference edges are carried forward verbatim.\n */\n private recordSymbolReferences(c: EdgeCollector, decl: ImportDeclaration): void {\n const specifier = decl.getModuleSpecifierValue();\n for (const binding of namedImportBindings(decl)) {\n const dstId = this.resolveSymbolTarget(c, decl, binding.importedName);\n if (!dstId) continue;\n addWeightedEdge(\n c.agg,\n c.srcFileId,\n dstId,\n \"references\",\n specifier,\n bindingWeight(binding, c.usage),\n );\n }\n }\n\n /**\n * Resolve an imported name to the id of the `symbol` node for the export that\n * actually *declares* it — following re-exports through barrels via ts-morph's\n * own `getExportedDeclarations`, so `import { x } from \"./barrel\"` credits the\n * origin file's `x`, not the barrel. When ts-morph can't resolve the specifier\n * (e.g. an extensionless relative import), falls back to a filesystem-based\n * re-export walk that still sees through barrel hops (C-70). Returns null for\n * external / unresolved targets.\n * A name that resolves to no local declaration (an aliased re-export the\n * origin doesn't export under this name) yields a dangling edge, pruned after\n * assembly (`pruneDanglingReferences`).\n */\n private resolveSymbolTarget(\n c: EdgeCollector,\n decl: ImportDeclaration,\n importedName: string,\n ): string | null {\n const targetSf = decl.getModuleSpecifierSourceFile();\n if (targetSf) {\n const decls = targetSf.getExportedDeclarations().get(importedName);\n const originSf =\n decls && decls.length > 0 ? decls[0]!.getSourceFile() : targetSf;\n const originId = this.inRepoFileId(remapDistToSrc(originSf.getFilePath(), this.fileExists));\n return originId ? symbolId(originId, importedName) : null;\n }\n // ts-morph couldn't link the specifier (extensionless / out-of-project);\n // trace the target's re-export hops on disk so an import through an\n // extensionless barrel still credits the origin symbol (C-70).\n return resolveReExportOrigin(\n { project: this.ensureProject(), repoRoot: this.repoRoot },\n c.srcAbs,\n decl.getModuleSpecifierValue(),\n importedName,\n );\n }\n\n private recordReExportEdge(c: EdgeCollector, decl: ExportDeclaration): void {\n if (!decl.hasModuleSpecifier()) return;\n const specifier = decl.getModuleSpecifierValue();\n if (!specifier) return;\n const dstId = this.resolveTarget(c, specifier, decl);\n if (dstId) {\n addWeightedEdge(c.agg, c.srcFileId, dstId, \"re-exports\", specifier, reExportWeight(decl));\n }\n }\n\n /**\n * Resolve an import/export specifier to a graph node id (an in-repo file id or\n * an `external` node, creating the external node on first sight), or `null`\n * when it should not produce an edge.\n */\n private resolveTarget(\n c: EdgeCollector,\n specifier: string,\n decl: ImportDeclaration | ExportDeclaration,\n ): string | null {\n const internal =\n this.resolveInternal(decl.getModuleSpecifierSourceFile()) ??\n this.resolveRelativeInternal(c.srcAbs, specifier);\n if (internal) return internal;\n if (isRelativeSpecifier(specifier)) {\n // A relative import ts-morph could not resolve and that does not point at\n // a file on disk (e.g. an alias, or a genuinely missing target). Dropping\n // it is correct: bucketing it as an npm external produced `npm:..` junk\n // nodes and masked real internal edges for any out-of-project TS (C-44).\n return null;\n }\n const extId = externalId(specifier);\n if (!c.seenExternals.has(extId)) {\n c.seenExternals.add(extId);\n c.externalNodes.push({ id: extId, kind: \"external\", name: specifier });\n }\n return extId;\n }\n\n private resolveInternal(target: SourceFile | undefined): string | null {\n if (!target) return null;\n return this.inRepoFileId(remapDistToSrc(target.getFilePath(), this.fileExists));\n }\n\n /**\n * Resolve a relative specifier ts-morph failed to link by walking the\n * filesystem from the importing file. ts-morph's NodeNext resolution only\n * links relative imports that carry an explicit `.js` extension, so\n * extensionless bundler-style imports (`../types`, common in code outside the\n * tsconfig project such as `dashboard/`) resolve to nothing and would\n * otherwise fall through to the `npm:` external bucket (C-44). Resolves\n * through the ts-morph filesystem host so it honours in-memory test fixtures.\n */\n private resolveRelativeInternal(\n srcAbs: string,\n specifier: string,\n ): string | null {\n const abs = resolveRelativeAbs(\n this.ensureProject().getFileSystem(),\n srcAbs,\n specifier,\n );\n return abs ? inRepoFileId(this.repoRoot, abs) : null;\n }\n\n private inRepoFileId(abs: string): string | null {\n return inRepoFileId(this.repoRoot, abs);\n }\n}\n\nfunction isTypeScriptFile(file: ParsedFile): boolean {\n return file.language === \"typescript\" || file.language === \"tsx\";\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { Project, type FileSystemHost } from \"ts-morph\";\nimport { walkSourceFiles } from \"./file-walk.js\";\n\n/**\n * Where the indexer reads a tree from. Every path is absolute and node ids are\n * derived from it, so a source that is not the working tree (a git commit, say)\n * keeps ids byte-identical by answering for the same absolute paths.\n */\nexport interface IndexSource {\n /**\n * Source files under `rootDirs` that pass the ingest filter for `languages`,\n * deduped and sorted, so float metrics summed in file order match across sources.\n */\n listFiles(rootDirs: readonly string[], languages: readonly string[]): Promise<string[]>;\n /** UTF-8 content of a file; throws when it does not exist. */\n readFile(abs: string): string;\n fileExists(abs: string): boolean;\n /** The host ts-morph resolves imports and reads tsconfig through. */\n readonly fileSystem: FileSystemHost;\n /** Set when the source is a git commit rather than the working tree; undefined for the working tree. */\n readonly revision?: {\n /** The repo's toplevel, canonicalized with realpath. */\n readonly repoRoot: string;\n readonly commit: string;\n /** Committer time, seconds since the epoch. */\n readonly commitEpoch: number;\n };\n}\n\nlet realFileSystem: FileSystemHost | undefined;\n\n/** ts-morph exports no RealFileSystemHost, but a bare Project builds one and hands it back. */\nfunction realFileSystemHost(): FileSystemHost {\n realFileSystem ??= new Project().getFileSystem();\n return realFileSystem;\n}\n\n/** The checked-out working tree, read through `node:fs`. The default source. */\nexport function workingTreeSource(): IndexSource {\n return {\n listFiles: async (rootDirs, languages) => (await walkSourceFiles(rootDirs, languages)).sort(),\n readFile: (abs) => readFileSync(abs, \"utf-8\"),\n fileExists: existsSync,\n get fileSystem() {\n return realFileSystemHost();\n },\n };\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { isExcludedDir, shouldIncludeFile } from \"@titan-design/code-parser\";\n\n/**\n * Recursively collect the source files under `rootDirs` that pass the ingest\n * filter for `languages`, deduped by absolute path across roots (walk order\n * preserved). Extracted from the indexer (C-61): as a function nested inside the\n * per-root loop, the recursive walker carried a cognitive-complexity nesting\n * bonus that made it the indexer's single most complex function (cx 19, above\n * the exported entry point). Hoisting it here — one recursion helper, one\n * directory branch — drops it well under budget and makes the walker unit-\n * testable in isolation.\n */\nexport async function walkSourceFiles(\n rootDirs: readonly string[],\n languages: readonly string[],\n): Promise<string[]> {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const rootDir of rootDirs) {\n await collectFiles(rootDir, rootDir, languages, seen, out);\n }\n return out;\n}\n\nasync function collectFiles(\n dir: string,\n rootDir: string,\n languages: readonly string[],\n seen: Set<string>,\n out: string[],\n): Promise<void> {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n // Prune excluded directories (node_modules, dist, .git, …) instead of\n // recursing into them: `shouldIncludeFile` already rejects every file\n // beneath them, so descending only pays to `readdir` a potentially multi-GB\n // tree and discard all of it. Pruning here changes no output but makes\n // `graph index` on a repo with installed dependencies orders of magnitude\n // faster (found dogfooding on a pnpm monorepo — a whole-repo index hung in\n // node_modules for minutes).\n if (entry.isDirectory()) {\n if (isExcludedDir(entry.name)) continue;\n await collectFiles(full, rootDir, languages, seen, out);\n } else if (entry.isFile() && !seen.has(full)) {\n const relative = path.relative(rootDir, full);\n if (shouldIncludeFile(relative, [...languages])) {\n seen.add(full);\n out.push(full);\n }\n }\n }\n}\n","import * as path from \"node:path\";\nimport { getLanguageFromPath } from \"@titan-design/code-parser\";\nimport { fileId, moduleId, parentModuleId } from \"./ids.js\";\nimport type { GraphNode } from \"../types.js\";\n\n/**\n * Build the `file` + `module` nodes for a source file from its path alone.\n * Path-derived and deterministic, so the incremental indexer can reconstruct an\n * unchanged file's nodes without re-parsing it — they are byte-for-byte the same\n * nodes the extractor would emit. Keep this the single source of truth for\n * file/module node shape.\n */\nexport function buildFileModuleNodes(repoRoot: string, absPath: string): GraphNode[] {\n const fId = fileId(repoRoot, absPath);\n const mId = moduleId(repoRoot, absPath);\n const parentId = parentModuleId(mId) ?? undefined;\n const language = getLanguageFromPath(absPath) ?? \"typescript\";\n return [\n { id: fId, kind: \"file\", name: path.basename(fId), parentId: mId, language },\n { id: mId, kind: \"module\", name: path.basename(mId), parentId, language },\n ];\n}\n","import * as path from \"node:path\";\n\nconst MODULE_EXT_RE = /\\.(?:tsx|ts|jsx|js|mts|cts|mjs|cjs|py)$/;\n\nfunction toPosix(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n\nfunction repoRelative(repoRoot: string, absPath: string): string {\n const rel = path.relative(repoRoot, absPath);\n return toPosix(rel);\n}\n\nexport function fileId(repoRoot: string, absPath: string): string {\n return repoRelative(repoRoot, absPath);\n}\n\nexport function moduleId(repoRoot: string, absPath: string): string {\n const rel = repoRelative(repoRoot, absPath);\n return rel.replace(MODULE_EXT_RE, \"\");\n}\n\nexport function parentModuleId(id: string): string | null {\n const idx = id.lastIndexOf(\"/\");\n if (idx < 0) return null;\n return id.slice(0, idx);\n}\n\nexport function packageId(name: string): string {\n return name;\n}\n\nexport { SYMBOL_ID_SEP, parseSymbolId, symbolId } from \"./symbol-id.js\";\n\nexport function externalId(specifier: string): string {\n if (specifier.startsWith(\"node:\")) {\n return specifier;\n }\n return `npm:${bareName(specifier)}`;\n}\n\nfunction bareName(specifier: string): string {\n if (specifier.startsWith(\"@\")) {\n const parts = specifier.split(\"/\");\n return parts.slice(0, 2).join(\"/\");\n }\n const slash = specifier.indexOf(\"/\");\n return slash < 0 ? specifier : specifier.slice(0, slash);\n}\n","import {\n Node,\n SyntaxKind,\n type ExportDeclaration,\n type Identifier,\n type ImportDeclaration,\n type SourceFile,\n} from \"ts-morph\";\nimport type { EdgeKind, GraphEdge } from \"../types.js\";\n\n/**\n * Reference-count edge weighting (C-51). File-level import/re-export edges carry\n * a `weight` on `attrs` measuring how heavily the source file leans on the\n * target — not merely whether it imports from it. A file that calls one imported\n * helper 30× is more coupled than one that names 30 helpers once; a binary edge\n * cannot tell them apart. Everything here is source-local (it reads only the\n * importing file's text), so the weight stays sound under incremental reuse,\n * which reparses a file only when its own content changes.\n */\n\n/**\n * Fold a specifier into the aggregate, summing weights so parallel imports of\n * one module (e.g. a value import plus a type import) collapse to a single\n * edge whose weight is their combined reference count.\n */\nexport function addWeightedEdge(\n agg: Map<string, GraphEdge>,\n srcId: string,\n dstId: string,\n kind: EdgeKind,\n specifier: string,\n weight: number,\n): void {\n const key = JSON.stringify([kind, dstId]);\n const existing = agg.get(key);\n if (existing) {\n (existing.attrs as { weight: number }).weight += weight;\n return;\n }\n agg.set(key, { srcId, dstId, kind, attrs: { specifier, weight } });\n}\n\n/**\n * How many times the importing file actually uses the symbols it brings in,\n * floored at 1 so a live-but-unused import (or a `import \"./x\"` side-effect\n * import, which binds nothing) still reads as a real dependency.\n */\nexport function importWeight(\n decl: ImportDeclaration,\n usage: Map<string, number>,\n): number {\n const names = importBindingNames(decl);\n if (names.length === 0) return 1; // side-effect import: `import \"./x\"`\n const used = names.reduce((sum, n) => sum + (usage.get(n) ?? 0), 0);\n return Math.max(used, 1);\n}\n\n/**\n * One named or default import binding, pairing the name as *exported by the\n * target module* (what a symbol node is keyed on) with the *local* alias in\n * this file (what usage counts key on). Namespace imports (`import * as ns`)\n * are deliberately excluded: they reference the module as a whole, not any one\n * export, so per-symbol attribution isn't well-defined — the file-level\n * `imports` edge still accounts for them (C-53).\n */\nexport interface ImportBinding {\n importedName: string;\n localName: string;\n}\n\nexport function namedImportBindings(decl: ImportDeclaration): ImportBinding[] {\n const out: ImportBinding[] = [];\n const def = decl.getDefaultImport();\n if (def) out.push({ importedName: \"default\", localName: def.getText() });\n for (const spec of decl.getNamedImports()) {\n out.push({\n importedName: spec.getNameNode().getText(),\n localName: (spec.getAliasNode() ?? spec.getNameNode()).getText(),\n });\n }\n return out;\n}\n\n/**\n * Per-binding reference weight: how many times this file uses the imported\n * symbol, floored at 1 so a named-but-only-referenced-once import still reads\n * as a real dependency (naming a symbol is itself a use).\n */\nexport function bindingWeight(\n binding: ImportBinding,\n usage: Map<string, number>,\n): number {\n return Math.max(usage.get(binding.localName) ?? 0, 1);\n}\n\nfunction importBindingNames(decl: ImportDeclaration): string[] {\n const names: string[] = [];\n const def = decl.getDefaultImport();\n if (def) names.push(def.getText());\n const ns = decl.getNamespaceImport();\n if (ns) names.push(ns.getText());\n for (const spec of decl.getNamedImports()) {\n names.push((spec.getAliasNode() ?? spec.getNameNode()).getText());\n }\n return names;\n}\n\n/**\n * Re-export edges have no local usage to count — the names pass straight\n * through — so weight them by how many names cross the boundary: the count of\n * re-exported specifiers, or 1 for `export * from`.\n */\nexport function reExportWeight(decl: ExportDeclaration): number {\n if (decl.isNamespaceExport()) return 1;\n return Math.max(decl.getNamedExports().length, 1);\n}\n\n/**\n * Count identifier occurrences per name across the file in a single pass,\n * skipping the import/export declarations themselves and property *name*\n * positions (`obj.foo`, `{ foo: … }`) — those name a member, not a reference to\n * an imported binding. Binding names are unique per file (TS forbids\n * redeclaration), so a name's total attributes cleanly to one edge. Local\n * shadowing (a variable reusing an imported name) can over-count; acceptable\n * for a coupling-strength signal.\n */\nexport function buildLocalUsageCounts(\n sourceFile: SourceFile,\n): Map<string, number> {\n const counts = new Map<string, number>();\n for (const id of sourceFile.getDescendantsOfKind(SyntaxKind.Identifier)) {\n if (id.getFirstAncestorByKind(SyntaxKind.ImportDeclaration)) continue;\n if (id.getFirstAncestorByKind(SyntaxKind.ExportDeclaration)) continue;\n if (isPropertyNamePosition(id)) continue;\n const text = id.getText();\n counts.set(text, (counts.get(text) ?? 0) + 1);\n }\n return counts;\n}\n\nfunction isPropertyNamePosition(id: Identifier): boolean {\n const parent = id.getParent();\n if (Node.isPropertyAccessExpression(parent) && parent.getNameNode() === id) {\n return true;\n }\n if (Node.isPropertyAssignment(parent) && parent.getNameNode() === id) {\n return true;\n }\n return false;\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/** Node types the TypeScript grammar emits for a class: declarations, abstract declarations and class expressions. */\nexport const TS_CLASS_TYPES: ReadonlySet<string> = new Set([\n \"class_declaration\",\n \"abstract_class_declaration\",\n \"class\",\n]);\n\n/** Function declarations that carry their own name: plain, generator and method. */\nexport const TS_FUNCTION_DECL_TYPES: ReadonlySet<string> = new Set([\n \"function_declaration\",\n \"generator_function_declaration\",\n \"method_definition\",\n]);\n\n/** Function values that take the name of the `const`/`let` they are bound to. */\nexport const TS_BOUND_FUNCTION_TYPES: ReadonlySet<string> = new Set([\n \"arrow_function\",\n \"function_expression\",\n \"generator_function\",\n]);\n\n/** Declarations that name the scope they open. */\nconst TS_NAMED_SCOPES = new Set([\n ...TS_CLASS_TYPES,\n ...TS_FUNCTION_DECL_TYPES,\n \"internal_module\",\n]);\n\n/** Values that take the name they are bound to, or open an anonymous scope when unbound. */\nconst TS_BOUND_SCOPES = new Set([\n \"class\",\n ...TS_BOUND_FUNCTION_TYPES,\n \"object\",\n]);\n\nconst PY_NAMED_SCOPES = new Set([\"function_definition\", \"class_definition\"]);\n\n/** The segment an unbound callback, object or class adds, so its members never merge with a named declaration. */\nexport const ANONYMOUS_SCOPE = \"<anonymous>\";\n\n/** Join an enclosing scope path and a declared name into the dotted name a symbol id carries. */\nexport function qualify(scope: string, name: string): string {\n return scope ? `${scope}.${name}` : name;\n}\n\n/**\n * The name a value is bound to: `const x = …`, a class field `x = …`, an object\n * key `x: …`, or `default` for `export default`. Null for a value passed as an\n * argument or returned, which has no stable name.\n */\nfunction bindingName(node: Node): string | null {\n const parent = node.parent;\n if (!parent) return null;\n if (parent.type === \"variable_declarator\" || parent.type === \"public_field_definition\") {\n return parent.childForFieldName(\"name\")?.text ?? null;\n }\n if (parent.type === \"pair\") return parent.childForFieldName(\"key\")?.text ?? null;\n if (parent.type === \"export_statement\") return \"default\";\n return null;\n}\n\n/** The segment this node adds to its descendants' scope path, or null when it opens no named scope. */\nfunction scopeSegment(node: Node, python: boolean): string | null {\n if (python) {\n return PY_NAMED_SCOPES.has(node.type) ? (node.childForFieldName(\"name\")?.text ?? null) : null;\n }\n const own = TS_NAMED_SCOPES.has(node.type) ? node.childForFieldName(\"name\")?.text : undefined;\n if (own) return own;\n if (!TS_BOUND_SCOPES.has(node.type)) return null;\n return bindingName(node) ?? ANONYMOUS_SCOPE;\n}\n\n/** Consecutive anonymous scopes collapse to one segment: nesting depth is not identity. */\nfunction enter(scope: string, segment: string | null): string {\n if (!segment) return scope;\n if (segment === ANONYMOUS_SCOPE && (scope === ANONYMOUS_SCOPE || scope.endsWith(`.${ANONYMOUS_SCOPE}`))) {\n return scope;\n }\n return qualify(scope, segment);\n}\n\n/**\n * Depth-first walk handing every node the dotted path of the scopes that\n * enclose it (`Job` for a method of `class Job`, `outer` for a function nested\n * in `outer`). A callback argument or an unbound object or class adds\n * `<anonymous>` rather than a position, so the path stays stable when\n * declarations are reordered.\n */\nexport function walkScopes(\n root: Node,\n python: boolean,\n visit: (node: Node, scope: string) => void,\n): void {\n const step = (node: Node, scope: string): void => {\n visit(node, scope);\n const inner = enter(scope, scopeSegment(node, python));\n for (const child of node.children) {\n if (child) step(child, inner);\n }\n };\n step(root, \"\");\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport { qualify, TS_BOUND_FUNCTION_TYPES, TS_FUNCTION_DECL_TYPES, walkScopes } from \"./scope-path.js\";\n\nconst TS_DECL_TYPES = new Set([\n ...TS_FUNCTION_DECL_TYPES,\n \"class_declaration\",\n \"abstract_class_declaration\",\n]);\n\nconst PY_DECL_TYPES = new Set([\"function_definition\", \"class_definition\"]);\n\n/** 1-based inclusive line span of a declaration, for coverage range-attribution (C-63). */\nexport interface LineSpan {\n startLine: number;\n endLine: number;\n}\n\n/** One declaration: its own name, its scope-qualified name, and its line span. */\nexport interface Declaration {\n name: string;\n qualifiedName: string;\n span: LineSpan;\n}\n\n/**\n * Every function/method/class a file DECLARES, in source order (the model-B\n * symbol surface, C-64). A superset of the file's exports: internal helpers like\n * `mergeFragments` are included so they get a `symbol` node (and their\n * complexity + coverage) even though nothing imports them. Names come from the\n * same tree-sitter walk that computes complexity, so they never drift.\n * `qualifiedName` prefixes the enclosing named scopes (`Job.run`, `outer.inner`)\n * so same-named members of different classes or functions stay apart (TP-182).\n * Anonymous declarations (a default-exported arrow, inline callbacks) are skipped.\n */\nexport function collectDeclarations(file: ParsedFile): Declaration[] {\n const out: Declaration[] = [];\n forEachDeclaration(file, (name, qualifiedName, node) => {\n out.push({\n name,\n qualifiedName,\n span: { startLine: node.startPosition.row + 1, endLine: node.endPosition.row + 1 },\n });\n });\n return out;\n}\n\n/** Visit each declaration's name, scope-qualified name and the node its span and parameters come from. */\nexport function forEachDeclaration(\n file: ParsedFile,\n visit: (name: string, qualifiedName: string, node: Node) => void,\n): void {\n const python = file.language === \"python\";\n const declTypes = python ? PY_DECL_TYPES : TS_DECL_TYPES;\n walkScopes(file.tree.rootNode, python, (node, scope) => {\n const named = declaredNodeAt(node, declTypes);\n if (named) visit(named.name, qualify(scope, named.name), named.node);\n });\n}\n\n/**\n * Qualified declared names mapped to their 1-based line span (C-63 coverage\n * range-containment). One scope binds a name once, as TypeScript and Python do,\n * so a getter/setter pair, a Python property's accessors, and `@overload` stubs\n * share one entry; when a qualified name repeats, the last span wins.\n */\nexport function collectDeclaredSpans(file: ParsedFile): Map<string, LineSpan> {\n const spans = new Map<string, LineSpan>();\n for (const d of collectDeclarations(file)) spans.set(d.qualifiedName, d.span);\n return spans;\n}\n\n/** Declared names only — the Set view over {@link collectDeclaredSpans}. */\nexport function collectDeclaredNames(file: ParsedFile): Set<string> {\n return new Set(collectDeclaredSpans(file).keys());\n}\n\n/**\n * The declaration at this node — its name plus the node whose line span\n * represents it — or null. Mirrors source-metrics' `functionAt` handling of an\n * arrow, function or generator expression bound to a `const`/`let` (the span is the callable\n * body's node, so it contains the coverage `fnMap` loc), extended to classes.\n */\nfunction declaredNodeAt(\n node: Node,\n declTypes: ReadonlySet<string>,\n): { name: string; node: Node } | null {\n if (declTypes.has(node.type)) {\n const name = node.childForFieldName(\"name\")?.text;\n return name ? { name, node } : null;\n }\n if (TS_BOUND_FUNCTION_TYPES.has(node.type) && node.parent?.type === \"variable_declarator\") {\n const name = node.parent.childForFieldName(\"name\")?.text;\n return name ? { name, node } : null;\n }\n return null;\n}\n","import type { GraphEdge } from \"../types.js\";\n\n/**\n * The arguments at one resolved call site (TP-323). `args` holds each positional\n * argument's literal text, or null when it is not a literal. `spreadFrom` is the\n * index of the first `...xs` / `*xs`, after which positions are unknown; `kwargs`\n * and `kwSplat` are Python's keyword arguments and `**kw`.\n */\nexport interface CallSite {\n args: (string | null)[];\n kwargs?: Record<string, string | null>;\n spreadFrom?: number;\n kwSplat?: true;\n}\n\n/**\n * A callable's parameters, stored on its symbol node as `params` and `positionalParams`.\n * `params` excludes `this`, a Python method's receiver, and rest or `**kw` parameters;\n * the first `positional` of them can be passed by position, the rest only by keyword.\n */\nexport interface ParamShape {\n params: string[];\n positional: number;\n}\n\n/** Attrs a `calls` edge carries: every site where the caller calls the callee. */\nexport interface CallEdgeAttrs {\n sites: CallSite[];\n}\n\n/** One `calls` edge per caller and callee pair, with every call site appended to it. */\nexport function addCallSite(\n agg: Map<string, GraphEdge>,\n srcId: string,\n dstId: string,\n site: CallSite,\n): void {\n const key = JSON.stringify([srcId, dstId]);\n const existing = agg.get(key);\n if (existing) (existing.attrs as unknown as CallEdgeAttrs).sites.push(site);\n else agg.set(key, { srcId, dstId, kind: \"calls\", attrs: { sites: [site] } });\n}\n\n/** Symbol-node attrs for a shape; `positionalParams` is written only when some parameter is keyword-only. */\nexport function paramAttrs(shape: ParamShape | undefined): Record<string, unknown> {\n if (!shape) return {};\n return shape.positional === shape.params.length\n ? { params: shape.params }\n : { params: shape.params, positionalParams: shape.positional };\n}\n\n/** Read a shape back off a symbol node's attrs, or undefined for a node that is not a callable. */\nexport function readParamShape(attrs: Record<string, unknown> | undefined): ParamShape | undefined {\n const params = attrs?.params;\n if (!Array.isArray(params)) return undefined;\n const positional = typeof attrs?.positionalParams === \"number\" ? attrs.positionalParams : params.length;\n return { params: params as string[], positional };\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport { forEachDeclaration } from \"../declared-names.js\";\nimport type { ParamShape } from \"./call-sites.js\";\n\nconst TS_PARAM_TYPES = new Set([\"required_parameter\", \"optional_parameter\"]);\n\n/**\n * The parameter shape of every function and method a file declares, keyed by\n * qualified name. Classes carry none. From the same tree-sitter walk as the symbol\n * nodes, so a reused file's shapes ride forward on its symbol nodes unchanged.\n */\nexport function collectParamShapes(file: ParsedFile): Map<string, ParamShape> {\n const out = new Map<string, ParamShape>();\n forEachDeclaration(file, (_name, qualifiedName, node) => {\n const shape = file.language === \"python\" ? pythonShape(node) : tsShape(node);\n if (shape) out.set(qualifiedName, shape);\n });\n return out;\n}\n\nfunction tsShape(fn: Node): ParamShape | null {\n if (fn.type === \"class_declaration\") return null;\n const single = fn.childForFieldName(\"parameter\");\n if (single) return { params: [single.text], positional: 1 };\n const params: string[] = [];\n for (const param of fn.childForFieldName(\"parameters\")?.namedChildren ?? []) {\n if (!param || !TS_PARAM_TYPES.has(param.type)) continue;\n const pattern = param.childForFieldName(\"pattern\");\n if (!pattern || pattern.type === \"this\") continue;\n if (pattern.type === \"rest_pattern\") break;\n params.push(pattern.type === \"identifier\" ? pattern.text : `$${params.length}`);\n }\n return { params, positional: params.length };\n}\n\nfunction pythonShape(fn: Node): ParamShape | null {\n if (fn.type !== \"function_definition\") return null;\n const names: string[] = [];\n let positionalEnd: number | null = null;\n for (const param of fn.childForFieldName(\"parameters\")?.namedChildren ?? []) {\n if (!param) continue;\n if (param.type === \"keyword_separator\" || param.type === \"list_splat_pattern\") positionalEnd ??= names.length;\n const name = pythonParamName(param);\n if (name) names.push(name);\n }\n const receiver = hasReceiver(fn) && names.length > 0 ? 1 : 0;\n return { params: names.slice(receiver), positional: Math.max((positionalEnd ?? names.length) - receiver, 0) };\n}\n\n/** The bound name of a plain, typed or defaulted parameter; null for separators and `*args` / `**kw`. */\nfunction pythonParamName(param: Node): string | null {\n if (param.type === \"identifier\") return param.text;\n if (param.type === \"default_parameter\" || param.type === \"typed_default_parameter\") {\n return param.childForFieldName(\"name\")?.text ?? null;\n }\n if (param.type === \"typed_parameter\") {\n const first = param.namedChildren[0];\n return first?.type === \"identifier\" ? first.text : null;\n }\n return null;\n}\n\n/** A method defined directly in a class body takes `self` or `cls` first, unless it is a `@staticmethod`. */\nexport function hasReceiver(fn: Node): boolean {\n const decorated = fn.parent?.type === \"decorated_definition\" ? fn.parent : null;\n const block = (decorated ?? fn).parent;\n if (block?.type !== \"block\" || block.parent?.type !== \"class_definition\") return false;\n const decorators = decorated?.namedChildren.filter((c) => c?.type === \"decorator\") ?? [];\n return !decorators.some((d) => d?.text === \"@staticmethod\");\n}\n","import {\n Node,\n type ArrowFunction,\n type FunctionDeclaration,\n type FunctionExpression,\n type GetAccessorDeclaration,\n type MethodDeclaration,\n type SetAccessorDeclaration,\n type SourceFile,\n type VariableDeclaration,\n} from \"ts-morph\";\nimport { declarationQualifiedName } from \"./ts-scope.js\";\n\n/**\n * Persisted qualitative facts about a declaration (C-79): the one-line type\n * `signature` and the leading docstring `purpose`, so `graph context` can answer\n * \"what is this and how is it called\" without the reader opening the file — the\n * G1/G2 gap the C-74 spike found vs brain's codebase module.\n *\n * Both are pure syntactic projections of the declaration (params + explicit\n * return annotation + JSDoc), so an unchanged file's symbol nodes stay\n * byte-identical and the incremental indexer carries them forward. Inferred\n * types are only used when they carry no `import(\"…\")` module path — those embed\n * absolute paths that are non-deterministic and reuse-breaking.\n */\nexport interface SymbolText {\n signature?: string;\n purpose?: string;\n}\n\nconst MAX_SIGNATURE = 200;\nconst MAX_PURPOSE = 240;\n\ntype Callable =\n | FunctionDeclaration\n | MethodDeclaration\n | ArrowFunction\n | FunctionExpression;\n\n/** Signature + docstring for a ts-morph declaration node, best-effort. */\nexport function declarationText(decl: Node): SymbolText {\n const out: SymbolText = {};\n const signature = signatureOf(decl);\n if (signature) out.signature = signature;\n const purpose = purposeOf(decl);\n if (purpose) out.purpose = purpose;\n return out;\n}\n\n/**\n * The declaration a symbol name addresses. Symbol names are scope-qualified\n * (`Box.add`, `outer.helper`), which no file-level lookup can reach, so a miss\n * falls through to a qualified-name map of the whole file, built on the first\n * miss and shared by every later lookup through the same resolver. Index-time\n * signatures (model B, C-64) and on-pull deep AST both resolve through here, so\n * the two never disagree about which node a name means.\n */\nexport function createDeclarationLookup(sf: SourceFile): (name: string) => Node | undefined {\n let qualified: ReadonlyMap<string, Node> | undefined;\n return (name) => {\n const fileLevel = fileLevelDeclaration(sf, name);\n if (fileLevel) return fileLevel;\n qualified ??= qualifiedDeclarations(sf);\n return qualified.get(name);\n };\n}\n\n/** One-shot `createDeclarationLookup`, for a caller resolving a single name. */\nexport function lookupDeclaration(sf: SourceFile, name: string): Node | undefined {\n return createDeclarationLookup(sf)(name);\n}\n\nfunction fileLevelDeclaration(sf: SourceFile, name: string): Node | undefined {\n return (\n sf.getFunction(name) ??\n sf.getClass(name) ??\n sf.getInterface(name) ??\n sf.getTypeAlias(name) ??\n sf.getEnum(name) ??\n sf.getVariableDeclaration(name)\n );\n}\n\nfunction qualifiedDeclarations(sf: SourceFile): ReadonlyMap<string, Node> {\n const byName = new Map<string, Node>();\n sf.forEachDescendant((node) => {\n const name = declarationQualifiedName(node);\n if (name === null) return;\n const held = byName.get(name);\n if (!held || outranks(node, held)) byName.set(name, node);\n });\n return byName;\n}\n\n/**\n * Which of two declarations sharing a qualified name speaks for it: an\n * overload's implementation over its signatures (a declaration file has none,\n * so the first overload stands), and a getter over its setter, since the getter\n * carries the property's type. Otherwise the first in source order stays.\n */\nfunction outranks(candidate: Node, held: Node): boolean {\n if (Node.isOverloadable(held) && held.isOverload()) {\n return !(Node.isOverloadable(candidate) && candidate.isOverload());\n }\n return Node.isGetAccessorDeclaration(candidate) && Node.isSetAccessorDeclaration(held);\n}\n\nfunction signatureOf(decl: Node): string | undefined {\n if (Node.isFunctionDeclaration(decl) || Node.isMethodDeclaration(decl)) {\n return callableSignature(decl, decl.getName() ?? \"\");\n }\n if (Node.isGetAccessorDeclaration(decl) || Node.isSetAccessorDeclaration(decl)) {\n return accessorSignature(decl);\n }\n if (Node.isVariableDeclaration(decl)) return variableSignature(decl);\n if (Node.isClassDeclaration(decl)) return clamp(`class ${decl.getName() ?? \"\"}`.trim());\n if (Node.isInterfaceDeclaration(decl)) return clamp(`interface ${decl.getName()}`);\n if (Node.isTypeAliasDeclaration(decl)) {\n return clamp(`type ${decl.getName()} = ${oneLine(decl.getTypeNode()?.getText() ?? \"\")}`);\n }\n if (Node.isEnumDeclaration(decl)) return clamp(`enum ${decl.getName()}`);\n return undefined;\n}\n\nfunction variableSignature(decl: VariableDeclaration): string | undefined {\n const init = decl.getInitializer();\n if (init && (Node.isArrowFunction(init) || Node.isFunctionExpression(init))) {\n return callableSignature(init, decl.getName());\n }\n const typeNode = decl.getTypeNode();\n const type = typeNode ? oneLine(typeNode.getText()) : cleanType(() => decl.getType().getText());\n return type ? clamp(`${decl.getName()}: ${type}`) : undefined;\n}\n\n/**\n * An accessor is signed as the property it exposes, `name: type`: the getter's\n * declared or clean inferred return type, or for a lone setter its parameter's.\n */\nfunction accessorSignature(decl: GetAccessorDeclaration | SetAccessorDeclaration): string {\n const type = Node.isGetAccessorDeclaration(decl) ? returnType(decl) : setterType(decl);\n return clamp(type ? `${decl.getName()}: ${type}` : decl.getName());\n}\n\nfunction setterType(decl: SetAccessorDeclaration): string | undefined {\n const param = decl.getParameters()[0];\n if (!param) return undefined;\n const node = param.getTypeNode();\n return node ? oneLine(node.getText()) : cleanType(() => param.getType().getText());\n}\n\nfunction callableSignature(decl: Callable, name: string): string {\n const params = decl.getParameters().map((p) => oneLine(p.getText())).join(\", \");\n const ret = returnType(decl);\n return clamp(`${name}(${params})${ret ? `: ${ret}` : \"\"}`);\n}\n\nfunction returnType(decl: Callable | GetAccessorDeclaration): string | undefined {\n const node = decl.getReturnTypeNode();\n if (node) return oneLine(node.getText());\n return cleanType(() => decl.getReturnType().getText());\n}\n\n/**\n * Inferred type text, but only when it carries no `import(\"…\")` module path\n * (those embed absolute paths → non-deterministic + reuse-breaking). Returns\n * undefined rather than a dirty type, so the signature simply omits it.\n */\nfunction cleanType(getText: () => string): string | undefined {\n let text: string;\n try {\n text = getText();\n } catch {\n return undefined;\n }\n if (!text || text.includes(\"import(\")) return undefined;\n return oneLine(text);\n}\n\nfunction purposeOf(decl: Node): string | undefined {\n const docs = jsDocsFor(decl);\n if (!docs || docs.length === 0) return undefined;\n const desc = docs[docs.length - 1]!.getDescription().trim();\n return desc ? clamp(oneLine(desc), MAX_PURPOSE) : undefined;\n}\n\nfunction jsDocsFor(decl: Node) {\n if (Node.isJSDocable(decl)) return decl.getJsDocs();\n if (Node.isVariableDeclaration(decl)) return decl.getVariableStatement()?.getJsDocs();\n return undefined;\n}\n\nfunction oneLine(s: string): string {\n return s.replace(/\\s+/g, \" \").trim();\n}\n\nfunction clamp(s: string, max = MAX_SIGNATURE): string {\n return s.length > max ? `${s.slice(0, max - 1)}…` : s;\n}\n","import { Node } from \"ts-morph\";\nimport { ANONYMOUS_SCOPE, qualify } from \"../scope-path.js\";\n\n/**\n * The ts-morph mirror of `scope-path.ts`: the scope-qualified name tree-sitter\n * gives a declaration, computed from a ts-morph node so a declaration the type\n * checker resolves in any file maps onto that file's symbol id (TP-323). A name\n * the two walks disagree on yields an id with no symbol node, and the edge is\n * pruned, never misattributed.\n */\n\n/** The name a value takes from what it is bound to, as `bindingName` in scope-path.ts; null when unbound. */\nfunction bindingName(node: Node): string | null {\n const parent = node.getParent();\n if (Node.isVariableDeclaration(parent) || Node.isPropertyDeclaration(parent)) return parent.getName();\n if (Node.isPropertyAssignment(parent)) return parent.getNameNode().getText();\n if (Node.isExportAssignment(parent)) return \"default\";\n return null;\n}\n\n/** A class or function declaration's own name, or `default` for an unnamed default export. */\nfunction declaredName(node: Node & { getName(): string | undefined }): string | null {\n const name = node.getName();\n if (name) return name;\n return Node.isExportable(node) && node.isDefaultExport() ? \"default\" : null;\n}\n\n/** The segment a node adds to the scope of its descendants, or null when it opens no named scope. */\nfunction scopeSegment(node: Node): string | null {\n if (Node.isClassDeclaration(node) || Node.isFunctionDeclaration(node)) return declaredName(node);\n if (Node.isMethodDeclaration(node) || Node.isGetAccessorDeclaration(node) || Node.isSetAccessorDeclaration(node)) {\n return node.getName();\n }\n if (Node.isConstructorDeclaration(node)) return \"constructor\";\n if (Node.isModuleDeclaration(node)) return node.hasNamespaceKeyword() ? node.getName() : null;\n if (Node.isClassExpression(node) && node.getName()) return node.getName() ?? null;\n const bound =\n Node.isArrowFunction(node) ||\n Node.isFunctionExpression(node) ||\n Node.isClassExpression(node) ||\n Node.isObjectLiteralExpression(node);\n return bound ? (bindingName(node) ?? ANONYMOUS_SCOPE) : null;\n}\n\n/** The dotted scope path enclosing `node`, collapsing consecutive anonymous segments. */\nexport function scopeOf(node: Node): string {\n const segments = node\n .getAncestors()\n .map(scopeSegment)\n .filter((s): s is string => s !== null)\n .reverse();\n let scope = \"\";\n for (const segment of segments) {\n const repeatsAnonymous =\n segment === ANONYMOUS_SCOPE && (scope === ANONYMOUS_SCOPE || scope.endsWith(`.${ANONYMOUS_SCOPE}`));\n if (!repeatsAnonymous) scope = qualify(scope, segment);\n }\n return scope;\n}\n\n/**\n * The qualified name of a declaration that has a symbol node: a function,\n * method, accessor, constructor or class, or a variable bound to an arrow or\n * function expression. Null for anything else (a parameter, an interface member).\n */\nexport function declarationQualifiedName(decl: Node): string | null {\n if (Node.isVariableDeclaration(decl)) {\n const init = decl.getInitializer();\n const callable = Node.isArrowFunction(init) || Node.isFunctionExpression(init);\n return callable ? qualify(scopeOf(decl), decl.getName()) : null;\n }\n if (Node.isArrowFunction(decl) || Node.isFunctionExpression(decl)) {\n const parent = decl.getParent();\n return Node.isVariableDeclaration(parent) ? qualify(scopeOf(parent), parent.getName()) : null;\n }\n const isDeclaration =\n Node.isFunctionDeclaration(decl) ||\n Node.isClassDeclaration(decl) ||\n Node.isMethodDeclaration(decl) ||\n Node.isGetAccessorDeclaration(decl) ||\n Node.isSetAccessorDeclaration(decl) ||\n Node.isConstructorDeclaration(decl);\n const own = isDeclaration ? scopeSegment(decl) : null;\n return own ? qualify(scopeOf(decl), own) : null;\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { SourceFile } from \"ts-morph\";\nimport { collectDeclaredSpans, type LineSpan } from \"../declared-names.js\";\nimport { fileId, symbolId } from \"./ids.js\";\nimport { paramAttrs, type ParamShape } from \"./call-sites.js\";\nimport { collectParamShapes } from \"./callable-params.js\";\nimport { createDeclarationLookup, declarationText, type SymbolText } from \"./symbol-signature.js\";\nimport type { GraphNode } from \"../types.js\";\n\n/**\n * A `symbol` node for a declaration, tagging whether it is exported (C-64) and,\n * when it is a function/method/class, its 1-based line span (C-63) so coverage\n * can be attributed by range containment. A span-less symbol (an exported type or\n * const value) just carries `exported`. When ts-morph resolves the declaration it\n * also carries a one-line `signature` and docstring `purpose` (C-79) — both\n * omitted (not stored as null) when unavailable, so attrs stay byte-identical for\n * incremental reuse.\n */\nfunction makeSymbolNode(\n fileId: string,\n name: string,\n exported: boolean,\n span: LineSpan | undefined,\n text: SymbolText,\n shape: ParamShape | undefined,\n): GraphNode {\n const attrs: Record<string, unknown> = { exported, ...paramAttrs(shape) };\n if (span) {\n attrs.startLine = span.startLine;\n attrs.endLine = span.endLine;\n }\n if (text.signature) attrs.signature = text.signature;\n if (text.purpose) attrs.purpose = text.purpose;\n return {\n id: symbolId(fileId, name),\n kind: \"symbol\",\n name,\n parentId: fileId,\n language: \"typescript\",\n attrs,\n };\n}\n\n/**\n * A `symbol` node per declaration a file owns (model B, C-64). Two sources, both\n * source-local so an unchanged file's symbol nodes are byte-identical across runs\n * and the incremental indexer carries them forward without re-parsing:\n *\n * - **Exported declarations** (`exported: true`) — from ts-morph's\n * `getExportedDeclarations`, which barrel-resolves. Names this file merely\n * re-exports are skipped: they belong to the origin file's symbol nodes, so\n * `references` edges resolved through a barrel land on the file that does the\n * work, not the hub (C-53 / C-55). Covers functions, classes, types, and\n * exported const values alike — the reference-edge targets.\n * - **Non-exported functions / methods / classes** (`exported: false`) — from the\n * tree-sitter declared-name walk (same parser as complexity), so an internal\n * helper like `mergeFragments` gets a node and, by name match, its own\n * complexity, closing the C-59 Dossier gap. Internal *non-callable* bindings\n * (plain const values) are intentionally excluded — only functions/methods/\n * classes.\n */\nexport function buildSymbolNodes(\n repoRoot: string,\n sourceFile: SourceFile,\n file: ParsedFile,\n): GraphNode[] {\n const fId = fileId(repoRoot, sourceFile.getFilePath());\n const spans = collectDeclaredSpans(file);\n const shapes = collectParamShapes(file);\n const out: GraphNode[] = [];\n const exported = new Set<string>();\n for (const [name, decls] of sourceFile.getExportedDeclarations()) {\n const own = decls.find((d) => d.getSourceFile() === sourceFile);\n if (!own) continue;\n exported.add(name);\n out.push(makeSymbolNode(fId, name, true, spans.get(name), declarationText(own), shapes.get(name)));\n }\n const lookup = createDeclarationLookup(sourceFile);\n for (const [name, span] of spans) {\n if (exported.has(name)) continue;\n const decl = lookup(name);\n out.push(makeSymbolNode(fId, name, false, span, decl ? declarationText(decl) : {}, shapes.get(name)));\n }\n return out;\n}\n","import {\n Node,\n SyntaxKind,\n type ObjectBindingPattern,\n type SourceFile,\n} from \"ts-morph\";\nimport type { GraphEdge } from \"../types.js\";\nimport { symbolId } from \"./ids.js\";\nimport { addWeightedEdge } from \"./reference-weight.js\";\n\n/**\n * String-literal specifiers of dynamic `import(\"…\")` expressions in a file\n * (C-65). The static import graph only records `import`/`export` *declarations*,\n * so a module loaded lazily — e.g. `cli/src/index.ts` doing\n * `import(\"./commands/analyze.js\")` to register a command — otherwise has no\n * inbound edge and reads `fan_in` 0, falsely appearing dead. Capturing these\n * closes that blind spot for the common case.\n *\n * Only string-literal specifiers are returned; a computed specifier\n * (`import(variable)`) is genuinely unresolvable statically and is left out (a\n * documented blind spot, same class as DI/registry-string wiring).\n */\nexport function dynamicImportSpecifiers(sourceFile: SourceFile): string[] {\n const out: string[] = [];\n for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {\n if (call.getExpression().getKind() !== SyntaxKind.ImportKeyword) continue;\n const arg = call.getArguments()[0];\n if (arg && arg.getKind() === SyntaxKind.StringLiteral) {\n out.push(arg.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralText());\n }\n }\n return out;\n}\n\n/** One export pulled out of a destructured dynamic import. */\ninterface DynamicImportBinding {\n specifier: string;\n /** The name as exported by the target module (property name, not local alias). */\n importedName: string;\n}\n\n/**\n * Destructured bindings of a dynamic import — `const { runX } = await import(\"…\")`\n * — pairing each pulled-out export with its target module (C-68). This is the\n * lazy-command-loading pattern (the CLI registers a subcommand via\n * `const { runX } = await import(\"./x.js\")`); C-65 captured only the module\n * edge, so the target's export still read as unused despite being live. Emitting\n * a per-symbol `references` edge from these clears that dead-code false positive.\n *\n * Only object destructuring binds a specific export. `const ns = await import(…)`\n * (namespace) and `.then(m => m.x)` are excluded — the module `imports` edge\n * already accounts for the whole-module dependency, exactly as a static\n * namespace import is handled (C-53). The property name (not the local alias) is\n * returned, matching how a `symbol` node is keyed.\n */\nfunction dynamicImportBindings(\n sourceFile: SourceFile,\n): DynamicImportBinding[] {\n const out: DynamicImportBinding[] = [];\n for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {\n if (call.getExpression().getKind() !== SyntaxKind.ImportKeyword) continue;\n const arg = call.getArguments()[0];\n if (!arg || arg.getKind() !== SyntaxKind.StringLiteral) continue;\n const pattern = destructuredTargetOf(call);\n if (!pattern) continue;\n const specifier = arg.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralText();\n for (const importedName of destructuredNames(pattern)) {\n out.push({ specifier, importedName });\n }\n }\n return out;\n}\n\n/**\n * The object-binding pattern a dynamic `import()` call feeds, if the call is the\n * initializer of a `const { … } = (await) import(…)` declaration. Returns\n * undefined for a namespace binding, a `.then()` chain, or any non-initializer\n * position — those don't destructure a specific export.\n */\nfunction destructuredTargetOf(call: Node): ObjectBindingPattern | undefined {\n const parent = call.getParent();\n if (!parent) return undefined;\n const init = Node.isAwaitExpression(parent) ? parent : call;\n const decl = init.getParent();\n if (!decl || !Node.isVariableDeclaration(decl)) return undefined;\n if (decl.getInitializer() !== init) return undefined;\n const nameNode = decl.getNameNode();\n return Node.isObjectBindingPattern(nameNode) ? nameNode : undefined;\n}\n\n/**\n * Exported names bound by an object pattern: `{ runX }` → `runX`,\n * `{ runX: local }` → `runX` (the exported name, not the alias). A rest element\n * (`{ ...rest }`) binds no single export and is skipped.\n */\nfunction destructuredNames(pattern: ObjectBindingPattern): string[] {\n const names: string[] = [];\n for (const el of pattern.getElements()) {\n if (el.getDotDotDotToken()) continue;\n const nameNode = el.getPropertyNameNode() ?? el.getNameNode();\n names.push(nameNode.getText());\n }\n return names;\n}\n\n/**\n * Add a `references` edge (importer → target symbol) for each destructured\n * dynamic import in a file (C-68). Kept here rather than in the extractor class\n * so the churn-hot, LOC-bound extractor body stays minimal; specifier→file\n * resolution is delegated to the caller (it needs the ts-morph project's\n * filesystem host). A target the module doesn't export dangles and is pruned\n * after assembly (`pruneDanglingReferences`).\n */\nexport function recordDynamicSymbolRefEdges(\n sourceFile: SourceFile,\n srcFileId: string,\n agg: Map<string, GraphEdge>,\n resolveSpecifier: (specifier: string) => string | null,\n): void {\n for (const binding of dynamicImportBindings(sourceFile)) {\n const targetFileId = resolveSpecifier(binding.specifier);\n if (!targetFileId) continue;\n addWeightedEdge(\n agg,\n srcFileId,\n symbolId(targetFileId, binding.importedName),\n \"references\",\n binding.specifier,\n 1,\n );\n }\n}\n","import * as path from \"node:path\";\nimport type { FileSystemHost } from \"ts-morph\";\nimport { fileId } from \"./ids.js\";\n\n/** Source/compiled extensions a relative specifier may resolve to, in priority order. */\nexport const RESOLVABLE_EXTS = [\n \".ts\",\n \".tsx\",\n \".mts\",\n \".cts\",\n \".js\",\n \".jsx\",\n \".mjs\",\n \".cjs\",\n];\n\nexport function isRelativeSpecifier(specifier: string): boolean {\n return (\n specifier === \".\" ||\n specifier === \"..\" ||\n specifier.startsWith(\"./\") ||\n specifier.startsWith(\"../\")\n );\n}\n\n/**\n * Candidate on-disk paths for a resolved relative import base, in priority\n * order: an explicit extension already present, then the source extensions,\n * then a NodeNext `.js`→`.ts` remap, then `index.*` for directory imports.\n */\nexport function* relativeResolutionCandidates(base: string): Iterable<string> {\n yield base;\n for (const ext of RESOLVABLE_EXTS) yield base + ext;\n const jsExt = /\\.(?:jsx?|mjs|cjs)$/.exec(base);\n if (jsExt) {\n const stem = base.slice(0, base.length - jsExt[0].length);\n for (const ext of RESOLVABLE_EXTS) yield stem + ext;\n }\n for (const ext of RESOLVABLE_EXTS) yield path.join(base, \"index\" + ext);\n}\n\n/**\n * Resolve a relative specifier from a file to an on-disk absolute path via the\n * ts-morph filesystem host (honours in-memory test fixtures), or null. ts-morph's\n * NodeNext resolution only links relative imports carrying an explicit `.js`\n * extension, so extensionless bundler-style imports (`../types`, common outside\n * the tsconfig project) need this fallback (C-44).\n */\nexport function resolveRelativeAbs(\n fs: FileSystemHost,\n fromAbs: string,\n specifier: string,\n): string | null {\n if (!isRelativeSpecifier(specifier)) return null;\n const base = path.resolve(path.dirname(fromAbs), specifier);\n for (const candidate of relativeResolutionCandidates(base)) {\n if (fs.fileExistsSync(candidate)) return candidate;\n }\n return null;\n}\n\n/** Map an abs path to an in-repo file id, or null if out of tree / in node_modules. */\nexport function inRepoFileId(repoRoot: string, abs: string): string | null {\n const relative = path.relative(repoRoot, abs);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) return null;\n if (relative.split(path.sep).includes(\"node_modules\")) return null;\n return fileId(repoRoot, abs);\n}\n\n// ts-morph resolves workspace imports like `@codewatch/analyzer` to the\n// package's `types` entry (`<pkg>/dist/index.d.ts`), but the indexer's file\n// walker excludes `dist/` and `.d.ts`. Without remapping, every cross-package\n// edge points to a nonexistent node and the rendered graph fails to construct.\nexport function remapDistToSrc(abs: string, fileExists: (abs: string) => boolean): string {\n const m = /^(.*)[\\\\/]dist[\\\\/](.+)\\.d\\.ts$/.exec(abs);\n if (!m) return abs;\n const base = m[1]!;\n const sub = m[2]!;\n for (const ext of [\".ts\", \".tsx\"]) {\n const candidate = path.join(base, \"src\", sub + ext);\n if (fileExists(candidate)) return candidate;\n }\n return abs;\n}\n\n/**\n * `node_modules/@types` dirs from `repoRoot` up to the filesystem root: TypeScript's\n * default type-root walk, anchored at the indexed repo instead of `process.cwd()`.\n */\nexport function repoTypeRoots(repoRoot: string): string[] {\n const roots: string[] = [];\n for (let dir = path.resolve(repoRoot); ; dir = path.dirname(dir)) {\n roots.push(path.join(dir, \"node_modules\", \"@types\"));\n if (path.dirname(dir) === dir) return roots;\n }\n}\n","import type { ExportDeclaration, Project, SourceFile } from \"ts-morph\";\nimport { symbolId } from \"./ids.js\";\nimport { inRepoFileId, resolveRelativeAbs } from \"./module-resolution.js\";\n\n/** Context the re-export walk needs: the ts-morph project and the repo root. */\nexport interface ReExportCtx {\n project: Project;\n repoRoot: string;\n}\n\n/**\n * Trace an imported name to the id of the `symbol` node for the export that\n * physically DECLARES it, walking re-export hops on disk (C-70). ts-morph's own\n * `getExportedDeclarations` already sees through barrels whose specifiers it can\n * resolve; this covers the case it can't — extensionless / out-of-project\n * relative specifiers (the tRPC pattern) — by resolving `specifier` from\n * `importerAbs` and following `export { x } from './b'` and `export * from './b'`\n * hops by hand. Returns null (→ a dangling edge, pruned after assembly) when the\n * name is neither declared here nor forwarded onward.\n */\nexport function resolveReExportOrigin(\n ctx: ReExportCtx,\n importerAbs: string,\n specifier: string,\n name: string,\n): string | null {\n const fs = ctx.project.getFileSystem();\n const targetAbs = resolveRelativeAbs(fs, importerAbs, specifier);\n return targetAbs ? walkReExports(ctx, targetAbs, name, new Set()) : null;\n}\n\nfunction walkReExports(\n ctx: ReExportCtx,\n fileAbs: string,\n name: string,\n visited: Set<string>,\n): string | null {\n if (visited.has(fileAbs)) return null;\n visited.add(fileAbs);\n // The indexer adds files to the project one at a time as it extracts them, so\n // a barrel/origin file on this walk may not be loaded yet — pull it from the\n // filesystem host on demand (cached thereafter).\n const sf =\n ctx.project.getSourceFile(fileAbs) ??\n ctx.project.addSourceFileAtPathIfExists(fileAbs);\n if (!sf) return null;\n if (declaresExportLocally(sf, name)) {\n const id = inRepoFileId(ctx.repoRoot, fileAbs);\n return id ? symbolId(id, name) : null;\n }\n const fs = ctx.project.getFileSystem();\n for (const ed of sf.getExportDeclarations()) {\n const spec = ed.getModuleSpecifierValue();\n if (!spec) continue;\n const inward = reExportInwardName(ed, name);\n if (inward === null) continue;\n const targetAbs = resolveRelativeAbs(fs, fileAbs, spec);\n if (!targetAbs) continue;\n const origin = walkReExports(ctx, targetAbs, inward, visited);\n if (origin) return origin;\n }\n return null;\n}\n\n/**\n * Whether `sf` physically declares an export named `name` — the same test\n * `buildSymbolNodes` uses to decide a name is this file's own symbol, so a\n * re-export walk that stops here lands on a symbol node that actually exists.\n */\nfunction declaresExportLocally(sf: SourceFile, name: string): boolean {\n const decls = sf.getExportedDeclarations().get(name);\n return !!decls && decls.some((d) => d.getSourceFile() === sf);\n}\n\n/**\n * For a re-export `export ... from '...'`, the name to look up in the target\n * module when the outward name is `name`, or null if this declaration does not\n * forward `name`.\n * - `export { a as b } from '...'` forwards outward `b` ← inward `a`.\n * - `export * from '...'` forwards every name unchanged.\n * - `export * as ns from '...'` binds a namespace object, not member names, so\n * it never forwards an individual `name` (we don't attribute per-member).\n */\nfunction reExportInwardName(ed: ExportDeclaration, name: string): string | null {\n const named = ed.getNamedExports();\n if (named.length > 0) {\n for (const spec of named) {\n const outward = spec.getAliasNode()?.getText() ?? spec.getName();\n if (outward === name) return spec.getName();\n }\n return null;\n }\n if (ed.getNamespaceExport()) return null; // `export * as ns from`\n return name; // bare `export *`\n}\n","import { Node, SyntaxKind, type CallExpression, type NewExpression, type SourceFile } from \"ts-morph\";\nimport type { GraphEdge } from \"../types.js\";\nimport { addCallSite, type CallSite } from \"./call-sites.js\";\nimport { symbolId } from \"./ids.js\";\nimport { inRepoFileId, remapDistToSrc } from \"./module-resolution.js\";\nimport { declarationQualifiedName } from \"./ts-scope.js\";\n\nexport interface TsCallContext {\n srcFileId: string;\n /** Qualified names this file has symbol nodes for; a caller must be one of them. */\n localSymbols: ReadonlySet<string>;\n repoRoot: string;\n fileExists: (abs: string) => boolean;\n}\n\ntype Call = CallExpression | NewExpression;\n\n/**\n * `calls` edges from each call or `new` in a file to the in-repo symbol the type\n * checker resolves its callee to (TP-323). The caller is the nearest enclosing\n * declaration with a symbol node, or the file for a top-level call. A callee the\n * checker cannot resolve to exactly one in-repo declaration is dropped.\n */\nexport function collectTsCallEdges(sourceFile: SourceFile, ctx: TsCallContext): GraphEdge[] {\n const agg = new Map<string, GraphEdge>();\n sourceFile.forEachDescendant((node) => {\n if (!Node.isCallExpression(node) && !Node.isNewExpression(node)) return;\n const dstId = resolveCallee(node, ctx);\n if (dstId) addCallSite(agg, callerId(node, ctx), dstId, tsCallSite(node));\n });\n return [...agg.values()];\n}\n\nfunction resolveCallee(call: Call, ctx: TsCallContext): string | null {\n const callee = call.getExpression();\n if (callee.getKind() === SyntaxKind.SuperKeyword) return null;\n const symbol = callee.getSymbol();\n if (!symbol) return null;\n const target = symbol.isAlias() ? symbol.getAliasedSymbol() : symbol;\n const ids = new Set<string>();\n for (const decl of target?.getDeclarations() ?? []) {\n const id = declarationId(decl, ctx);\n if (id === null) return null;\n ids.add(id);\n }\n return ids.size === 1 ? [...ids][0]! : null;\n}\n\nfunction declarationId(decl: Node, ctx: TsCallContext): string | null {\n const sf = decl.getSourceFile();\n const abs = remapDistToSrc(sf.getFilePath(), ctx.fileExists);\n if (sf.isDeclarationFile() && abs === sf.getFilePath()) return null;\n const fileId = inRepoFileId(ctx.repoRoot, abs);\n const name = fileId ? declarationQualifiedName(decl) : null;\n return fileId && name ? symbolId(fileId, name) : null;\n}\n\nfunction callerId(call: Call, ctx: TsCallContext): string {\n for (const ancestor of call.getAncestors()) {\n const name = declarationQualifiedName(ancestor);\n if (name && ctx.localSymbols.has(name)) return symbolId(ctx.srcFileId, name);\n }\n return ctx.srcFileId;\n}\n\nfunction tsCallSite(call: Call): CallSite {\n const site: CallSite = { args: [] };\n for (const arg of call.getArguments()) {\n if (Node.isSpreadElement(arg)) {\n site.spreadFrom ??= site.args.length;\n break;\n }\n site.args.push(literalText(arg));\n }\n return site;\n}\n\nconst LITERAL_KINDS = new Set([\n SyntaxKind.NumericLiteral,\n SyntaxKind.StringLiteral,\n SyntaxKind.NoSubstitutionTemplateLiteral,\n SyntaxKind.TrueKeyword,\n SyntaxKind.FalseKeyword,\n SyntaxKind.NullKeyword,\n]);\n\n/** The source text of a literal argument (a negative number included), else null. */\nfunction literalText(arg: Node): string | null {\n if (LITERAL_KINDS.has(arg.getKind())) return arg.getText();\n if (Node.isIdentifier(arg) && arg.getText() === \"undefined\") return \"undefined\";\n if (Node.isPrefixUnaryExpression(arg) && arg.getOperatorToken() === SyntaxKind.MinusToken) {\n return Node.isNumericLiteral(arg.getOperand()) ? arg.getText() : null;\n }\n return null;\n}\n","import * as path from \"node:path\";\nimport type { Node } from \"web-tree-sitter\";\nimport type { Extractor, ParsedFile } from \"@titan-design/code-parser\";\nimport { collectDeclaredSpans } from \"../declared-names.js\";\nimport { workingTreeSource, type IndexSource } from \"../index-source.js\";\nimport { buildFileModuleNodes } from \"./file-nodes.js\";\nimport { paramAttrs } from \"./call-sites.js\";\nimport { collectParamShapes } from \"./callable-params.js\";\nimport { collectPythonCallEdges } from \"./python-calls.js\";\nimport { externalId, fileId, symbolId } from \"./ids.js\";\nimport { inRepoFileId } from \"./module-resolution.js\";\nimport type { GraphEdge, GraphFragment, GraphNode } from \"../types.js\";\n\n/** `.py` candidates a dotted module path may resolve to, package `__init__` included. */\nfunction* candidates(base: string): Iterable<string> {\n yield `${base}.py`;\n yield path.join(base, \"__init__.py\");\n}\n\n/**\n * Tree-sitter Python extraction. Deliberately narrower than the ts-morph side:\n * no type checker, so imports resolve by dotted path against the tree rather\n * than by symbol resolution, and symbols are the declarations the same\n * tree-sitter walk already finds for complexity. Enough to place Python files in\n * the graph with their dependencies; a semantic Python layer is a follow-up.\n */\nexport class PythonGraphExtractor implements Extractor<GraphFragment> {\n readonly name = \"python-graph\";\n\n constructor(\n private readonly repoRoot: string,\n private readonly source: IndexSource = workingTreeSource(),\n ) {}\n\n extract(file: ParsedFile): GraphFragment[] {\n if (file.language !== \"python\") return [];\n const fId = fileId(this.repoRoot, file.filePath);\n const nodes = buildFileModuleNodes(this.repoRoot, file.filePath);\n nodes.push(...symbolNodes(fId, file));\n const { edges, externals } = this.collectImports(fId, file);\n const calls = collectPythonCallEdges(file, fId, (specifier) => this.resolveDotted(file.filePath, specifier));\n return [{ nodes: [...nodes, ...externals], edges: [...edges, ...calls] }];\n }\n\n private collectImports(\n srcId: string,\n file: ParsedFile,\n ): { edges: GraphEdge[]; externals: GraphNode[] } {\n const edges = new Map<string, GraphEdge>();\n const externals: GraphNode[] = [];\n for (const specifier of importSpecifiers(file.tree.rootNode)) {\n const internal = this.resolveDotted(file.filePath, specifier);\n const dstId = internal ?? externalId(specifier);\n if (!internal && !edges.has(dstId)) {\n externals.push({ id: dstId, kind: \"external\", name: specifier });\n }\n edges.set(dstId, { srcId, dstId, kind: \"imports\", attrs: { specifier, weight: 1 } });\n }\n return { edges: [...edges.values()], externals };\n }\n\n /**\n * Resolve `a.b.c` (or a leading-dot relative import) to an in-repo file id by\n * walking the dotted path from the importing file's package and then from the\n * repo root, which covers both intra-package and root-relative layouts.\n */\n private resolveDotted(fromAbs: string, specifier: string): string | null {\n const leadingDots = /^\\.*/.exec(specifier)?.[0].length ?? 0;\n const parts = specifier.slice(leadingDots).split(\".\").filter(Boolean);\n const relativeBase = path.resolve(path.dirname(fromAbs), \"../\".repeat(Math.max(leadingDots - 1, 0)));\n const roots = leadingDots > 0 ? [relativeBase] : [path.dirname(fromAbs), this.repoRoot];\n for (const root of roots) {\n for (const candidate of candidates(path.join(root, ...parts))) {\n const id = inRepoFileId(this.repoRoot, candidate);\n if (id !== null && this.source.fileExists(candidate)) return id;\n }\n }\n return null;\n }\n}\n\n/** Python identifiers hold no dot, so the last segment of a qualified name is the declared name. */\nfunction isPublicName(qualifiedName: string): boolean {\n return !qualifiedName.slice(qualifiedName.lastIndexOf(\".\") + 1).startsWith(\"_\");\n}\n\nfunction symbolNodes(fId: string, file: ParsedFile): GraphNode[] {\n const shapes = collectParamShapes(file);\n return [...collectDeclaredSpans(file)].map(([name, span]) => ({\n id: symbolId(fId, name),\n kind: \"symbol\" as const,\n name,\n parentId: fId,\n language: \"python\",\n attrs: {\n exported: isPublicName(name),\n startLine: span.startLine,\n endLine: span.endLine,\n ...paramAttrs(shapes.get(name)),\n },\n }));\n}\n\n/** Every module named by an `import x` / `from x import y` statement, in tree order. */\nfunction importSpecifiers(root: Node): string[] {\n const out: string[] = [];\n const visit = (node: Node): void => {\n if (node.type === \"import_statement\" || node.type === \"import_from_statement\") {\n const name = node.childForFieldName(\"module_name\");\n if (name) out.push(name.text);\n else for (const child of node.namedChildren) if (child?.type === \"dotted_name\") out.push(child.text);\n }\n for (const child of node.namedChildren) if (child) visit(child);\n };\n visit(root);\n return out;\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport { forEachDeclaration } from \"../declared-names.js\";\nimport { walkScopes } from \"../scope-path.js\";\nimport type { GraphEdge } from \"../types.js\";\nimport { addCallSite, type CallSite } from \"./call-sites.js\";\nimport { hasReceiver } from \"./callable-params.js\";\nimport { symbolId } from \"./ids.js\";\n\n/** Resolves a dotted module name, relative or absolute, from this file to an in-repo file id. */\nexport type ResolveModule = (specifier: string) => string | null;\n\ninterface PyCallContext {\n fileId: string;\n declarations: Map<string, Node>;\n imports: Map<string, { fileId: string; name: string }>;\n}\n\n/**\n * `calls` edges for the Python calls that resolve without a type checker\n * (TP-323): a bare name declared at module level in this file, a bare name bound\n * by `from <in-repo module> import <name>`, and `self.<name>(...)` to a method of\n * the enclosing class. Attribute chains, `module.func`, star imports and names a\n * parameter or nested def shadows are dropped. The caller is the enclosing def\n * or class, or the file for a module-level call.\n */\nexport function collectPythonCallEdges(file: ParsedFile, fileId: string, resolve: ResolveModule): GraphEdge[] {\n const declarations = new Map<string, Node>();\n forEachDeclaration(file, (_name, qualifiedName, node) => declarations.set(qualifiedName, node));\n const ctx: PyCallContext = { fileId, declarations, imports: fromImports(file.tree.rootNode, resolve) };\n const agg = new Map<string, GraphEdge>();\n walkScopes(file.tree.rootNode, true, (node, scope) => {\n if (node.type !== \"call\") return;\n const dst = resolveCallee(node.childForFieldName(\"function\"), scope, ctx);\n const args = node.childForFieldName(\"arguments\");\n if (!dst || args?.type !== \"argument_list\") return;\n const srcId = declarations.has(scope) ? symbolId(fileId, scope) : fileId;\n addCallSite(agg, srcId, dst, pythonCallSite(args));\n });\n return [...agg.values()];\n}\n\nfunction resolveCallee(callee: Node | null, scope: string, ctx: PyCallContext): string | null {\n if (callee?.type === \"identifier\") return resolveBareName(callee.text, scope, ctx);\n if (callee?.type === \"attribute\") return resolveSelfMethod(callee, scope, ctx);\n return null;\n}\n\nfunction resolveBareName(name: string, scope: string, ctx: PyCallContext): string | null {\n if (isShadowed(name, scope, ctx)) return null;\n const local = ctx.declarations.has(name);\n const imported = ctx.imports.get(name);\n if (local && imported) return null;\n if (local) return symbolId(ctx.fileId, name);\n return imported ? symbolId(imported.fileId, imported.name) : null;\n}\n\n/** True when a scope enclosing the call declares `name` as a nested def or class, or binds it as a parameter. */\nfunction isShadowed(name: string, scope: string, ctx: PyCallContext): boolean {\n const segments = scope ? scope.split(\".\") : [];\n for (let depth = segments.length; depth > 0; depth--) {\n const enclosing = segments.slice(0, depth).join(\".\");\n if (ctx.declarations.has(`${enclosing}.${name}`)) return true;\n if (parameterNames(ctx.declarations.get(enclosing)).includes(name)) return true;\n }\n return false;\n}\n\n/**\n * `self.name(...)` inside a method of class `C`: the def `name` on `C`, or else on\n * the first of `C`'s bases declared in this file that has it, depth first. The\n * receiver is the method's first parameter. A base from another file ends the search.\n */\nfunction resolveSelfMethod(callee: Node, scope: string, ctx: PyCallContext): string | null {\n const receiver = callee.childForFieldName(\"object\");\n const attr = callee.childForFieldName(\"attribute\")?.text;\n const method = ctx.declarations.get(scope);\n if (receiver?.type !== \"identifier\" || !attr || !method || !hasReceiver(method)) return null;\n if (parameterNames(method)[0] !== receiver.text) return null;\n const owner = findMethodOwner(scope.slice(0, scope.lastIndexOf(\".\")), attr, ctx, new Set());\n return owner ? symbolId(ctx.fileId, `${owner}.${attr}`) : null;\n}\n\nfunction findMethodOwner(className: string, attr: string, ctx: PyCallContext, seen: Set<string>): string | null {\n const cls = ctx.declarations.get(className);\n if (cls?.type !== \"class_definition\" || seen.has(className)) return null;\n seen.add(className);\n if (ctx.declarations.get(`${className}.${attr}`)?.type === \"function_definition\") return className;\n for (const base of cls.childForFieldName(\"superclasses\")?.namedChildren ?? []) {\n if (base?.type !== \"identifier\" || !ctx.declarations.has(base.text)) return null;\n const owner = findMethodOwner(base.text, attr, ctx, seen);\n if (owner) return owner;\n }\n return null;\n}\n\n/** Every parameter name of a def, receiver and `*args` / `**kw` included; empty for a class or nothing. */\nfunction parameterNames(def: Node | undefined): string[] {\n if (def?.type !== \"function_definition\") return [];\n const out: string[] = [];\n for (const param of def.childForFieldName(\"parameters\")?.namedChildren ?? []) {\n const id = param?.type === \"identifier\" ? param : param?.descendantsOfType(\"identifier\")[0];\n if (id) out.push(id.text);\n }\n return out;\n}\n\n/** Local names bound by `from <module> import <name> [as <alias>]` whose module resolves in-repo. */\nfunction fromImports(root: Node, resolve: ResolveModule): PyCallContext[\"imports\"] {\n const out: PyCallContext[\"imports\"] = new Map();\n for (const stmt of root.descendantsOfType(\"import_from_statement\")) {\n const moduleName = stmt?.childForFieldName(\"module_name\")?.text;\n const moduleFile = moduleName ? resolve(moduleName) : null;\n if (!stmt || !moduleFile) continue;\n for (const imported of stmt.childrenForFieldName(\"name\")) {\n const alias = imported?.type === \"aliased_import\" ? imported.childForFieldName(\"alias\")?.text : undefined;\n const name = imported?.type === \"aliased_import\" ? imported.childForFieldName(\"name\")?.text : imported?.text;\n if (name && !name.includes(\".\")) out.set(alias ?? name, { fileId: moduleFile, name });\n }\n }\n return out;\n}\n\nconst LITERAL_TYPES = new Set([\"integer\", \"float\", \"true\", \"false\", \"none\"]);\n\n/** The source text of a literal argument; an f-string or a concatenation is not one. */\nfunction literalText(arg: Node): string | null {\n if (LITERAL_TYPES.has(arg.type)) return arg.text;\n if (arg.type === \"string\") return arg.namedChildren.some((c) => c?.type === \"interpolation\") ? null : arg.text;\n if (arg.type === \"unary_operator\" && arg.text.startsWith(\"-\")) {\n const operand = arg.childForFieldName(\"argument\");\n return operand && (operand.type === \"integer\" || operand.type === \"float\") ? arg.text : null;\n }\n return null;\n}\n\nfunction pythonCallSite(argumentList: Node): CallSite {\n const site: CallSite = { args: [] };\n for (const arg of argumentList.namedChildren) {\n if (!arg || arg.type === \"comment\") continue;\n if (arg.type === \"list_splat\") site.spreadFrom ??= site.args.length;\n else if (arg.type === \"dictionary_splat\") site.kwSplat = true;\n else if (arg.type === \"keyword_argument\") addKeyword(site, arg);\n else if (site.spreadFrom === undefined) site.args.push(literalText(arg));\n }\n return site;\n}\n\nfunction addKeyword(site: CallSite, arg: Node): void {\n const name = arg.childForFieldName(\"name\")?.text;\n const value = arg.childForFieldName(\"value\");\n if (!name || !value) return;\n site.kwargs ??= {};\n site.kwargs[name] = literalText(value);\n}\n","import type { Extractor, ParsedFile } from \"@titan-design/code-parser\";\nimport { TsMorphGraphExtractor } from \"./ts-morph-extractor.js\";\nimport { PythonGraphExtractor } from \"./python-extractor.js\";\nimport type { GraphFragment } from \"../types.js\";\nimport type { IndexSource } from \"../index-source.js\";\n\nexport interface LanguageExtractorOptions {\n repoRoot: string;\n tsConfigPath?: string;\n source?: IndexSource;\n}\n\n/**\n * One extractor over every supported language: each delegate already returns an\n * empty fragment list for files it does not own, so dispatch is a fold. Keeps\n * `assembleFragments` language-agnostic.\n */\nexport class LanguageExtractor implements Extractor<GraphFragment> {\n readonly name = \"language-graph\";\n private readonly delegates: Extractor<GraphFragment>[];\n\n constructor(options: LanguageExtractorOptions) {\n const { repoRoot, tsConfigPath, source } = options;\n this.delegates = [\n new TsMorphGraphExtractor({ repoRoot, tsConfigPath, source }),\n new PythonGraphExtractor(repoRoot, source),\n ];\n }\n\n extract(file: ParsedFile): GraphFragment[] {\n return this.delegates.flatMap((delegate) => delegate.extract(file));\n }\n}\n","import * as path from \"node:path\";\nimport { detectGitToplevel, runGit } from \"./history/git.js\";\nimport { fileId, moduleId } from \"./extractors/ids.js\";\nimport type { IdAlias, IdAliasReason } from \"./types.js\";\n\nexport interface RenamePair {\n oldPath: string;\n newPath: string;\n similarity: number;\n}\n\nexport interface DetectRenamesOptions {\n repoRoot: string;\n fromCommit: string;\n toCommit?: string;\n similarityThreshold?: number;\n}\n\nexport function detectGitHead(repoRoot: string): string | null {\n return runGit(repoRoot, [\"rev-parse\", \"HEAD\"]);\n}\n\nexport function isInsideGitRepo(repoRoot: string): boolean {\n return runGit(repoRoot, [\"rev-parse\", \"--is-inside-work-tree\"]) === \"true\";\n}\n\nexport { detectGitToplevel };\n\n/** Resolve a ref (branch, tag, sha) to its current commit sha, or null. */\nexport function resolveGitRef(repoRoot: string, ref: string): string | null {\n return runGit(repoRoot, [\"rev-parse\", ref]);\n}\n\n/** Whether `ancestor` is reachable from `descendant`; false when either is unknown to the repo. */\nexport function isGitAncestor(repoRoot: string, ancestor: string, descendant: string): boolean {\n return runGit(repoRoot, [\"merge-base\", \"--is-ancestor\", ancestor, descendant]) !== null;\n}\n\nexport function detectRenames(\n options: DetectRenamesOptions,\n): RenamePair[] {\n const threshold = options.similarityThreshold ?? 80;\n const args = [\n \"diff\",\n `--find-renames=${threshold}%`,\n \"--name-status\",\n options.fromCommit,\n ];\n if (options.toCommit) args.push(options.toCommit);\n\n const out = runGit(options.repoRoot, args);\n if (out === null) return [];\n return parseRenameOutput(out);\n}\n\nexport function parseRenameOutput(text: string): RenamePair[] {\n const out: RenamePair[] = [];\n for (const rawLine of text.split(\"\\n\")) {\n const line = rawLine.trimEnd();\n if (!line) continue;\n const parts = line.split(\"\\t\");\n const status = parts[0] ?? \"\";\n if (!status.startsWith(\"R\") || parts.length < 3) continue;\n const similarity = parseInt(status.slice(1), 10);\n out.push({\n oldPath: parts[1]!,\n newPath: parts[2]!,\n similarity: Number.isFinite(similarity) ? similarity : 100,\n });\n }\n return out;\n}\n\nexport function classifyRename(\n oldPath: string,\n newPath: string,\n): IdAliasReason {\n return path.posix.dirname(oldPath) === path.posix.dirname(newPath)\n ? \"rename\"\n : \"move\";\n}\n\nexport function renameToAliases(\n repoRoot: string,\n pair: RenamePair,\n): IdAlias[] {\n const reason = classifyRename(pair.oldPath, pair.newPath);\n const oldAbs = path.join(repoRoot, pair.oldPath);\n const newAbs = path.join(repoRoot, pair.newPath);\n return [\n { oldId: fileId(repoRoot, oldAbs), newId: fileId(repoRoot, newAbs), reason },\n { oldId: moduleId(repoRoot, oldAbs), newId: moduleId(repoRoot, newAbs), reason },\n ];\n}\n\nexport function buildAliases(\n repoRoot: string,\n pairs: readonly RenamePair[],\n): IdAlias[] {\n const seen = new Set<string>();\n const out: IdAlias[] = [];\n for (const pair of pairs) {\n for (const alias of renameToAliases(repoRoot, pair)) {\n if (seen.has(alias.oldId)) continue;\n seen.add(alias.oldId);\n out.push(alias);\n }\n }\n return out;\n}\n","import type { SnapshotRow } from \"../types.js\";\n\n/** Snapshot attrs key naming the snapshot its id aliases were computed against; written from index version 0.15.0. */\nexport const ALIAS_BASE_ATTR = \"aliasBase\";\n\n/** Walks stop after this many snapshots, so a corrupt or enormous lineage cannot run away. */\nexport const DEFAULT_MAX_HOPS = 10_000;\n\nexport type LineageSnapshot = Pick<SnapshotRow, \"id\" | \"commitHash\" | \"attrs\">;\n\n/** Each snapshot's alias base, or null for a root: the tree the id_alias rows form across snapshots. */\nexport type Lineage = ReadonlyMap<number, number | null>;\n\nexport interface LineageStep {\n snapshotId: number;\n /** `forward` applies the snapshot's aliases (base to snapshot); `backward` undoes them. */\n direction: \"forward\" | \"backward\";\n}\n\nfunction recordedBase(snap: LineageSnapshot): number | null | undefined {\n if (!(ALIAS_BASE_ATTR in snap.attrs)) return undefined;\n const base = snap.attrs[ALIAS_BASE_ATTR];\n // Only an earlier snapshot can be a base, which keeps the lineage acyclic.\n return typeof base === \"number\" && base < snap.id ? base : null;\n}\n\n/**\n * The recorded base per snapshot. A snapshot written before 0.15.0 records none,\n * so it gets the newest earlier snapshot with a commit: the one the indexer diffed against then.\n */\nexport function buildLineage(snapshots: readonly LineageSnapshot[]): Lineage {\n const out = new Map<number, number | null>();\n let lastWithCommit: number | null = null;\n for (const snap of [...snapshots].sort((a, b) => a.id - b.id)) {\n const recorded = recordedBase(snap);\n out.set(snap.id, recorded === undefined ? lastWithCommit : recorded);\n if (snap.commitHash) lastWithCommit = snap.id;\n }\n return out;\n}\n\n/** The snapshot followed by its bases up to the root, newest first; `maxHops` bounds a hand-built lineage with a cycle. */\nexport function ancestry(lineage: Lineage, snapshotId: number, maxHops = DEFAULT_MAX_HOPS): number[] {\n const out: number[] = [];\n let current: number | null | undefined = snapshotId;\n while (current !== null && current !== undefined && out.length <= maxHops) {\n out.push(current);\n current = lineage.get(current);\n }\n return out;\n}\n\n/** Steps from one snapshot to another through their nearest common base, or null when they share none. */\nexport function lineagePath(\n lineage: Lineage,\n fromId: number,\n toId: number,\n maxHops = DEFAULT_MAX_HOPS,\n): LineageStep[] | null {\n const up = ancestry(lineage, fromId, maxHops);\n const down = ancestry(lineage, toId, maxHops);\n const upIndex = new Map(up.map((id, i) => [id, i]));\n const meet = down.findIndex((id) => upIndex.has(id));\n if (meet < 0) return null;\n const backward = up.slice(0, upIndex.get(down[meet]!)).map((id) => step(id, \"backward\"));\n const forward = down.slice(0, meet).reverse().map((id) => step(id, \"forward\"));\n return [...backward, ...forward];\n}\n\n/** Every snapshot from the lineage root down to `toId`, so an id from any ancestor resolves. */\nexport function rootPath(lineage: Lineage, toId: number, maxHops = DEFAULT_MAX_HOPS): LineageStep[] {\n return ancestry(lineage, toId, maxHops).reverse().map((id) => step(id, \"forward\"));\n}\n\nfunction step(snapshotId: number, direction: LineageStep[\"direction\"]): LineageStep {\n return { snapshotId, direction };\n}\n","import type { IdAlias, IdAliasReason } from \"../types.js\";\nimport { lineagePath, rootPath, type Lineage, type LineageStep } from \"./lineage.js\";\n\nexport type AliasLoader = (snapshotId: number) => readonly IdAlias[];\n\nexport interface AliasResolution {\n requestedId: string;\n /** The id in the target snapshot's id space; equal to `requestedId` when nothing moved. */\n id: string;\n /** Each alias applied in walk order; a backward step lists the alias it undid. */\n hops: IdAlias[];\n /** `move` when any hop changed directory, otherwise the last hop's reason; absent without hops. */\n reason?: IdAliasReason;\n}\n\nexport interface AliasChain {\n fromSnapshotId: number | null;\n toSnapshotId: number;\n /** False when the snapshots share no alias base; only the target's own aliases apply then, as before 0.15.0. */\n connected: boolean;\n steps: readonly LineageStep[];\n resolve(id: string): string;\n trace(id: string): AliasResolution;\n}\n\nexport interface AliasChainInput {\n lineage: Lineage;\n loadAliases: AliasLoader;\n /** Null resolves an id from any ancestor of `to`. */\n from: number | null;\n to: number;\n maxHops?: number;\n}\n\ninterface StepMap {\n direction: LineageStep[\"direction\"];\n byId: ReadonlyMap<string, IdAlias>;\n}\n\n// Sorted so an inverted merge (two old ids, one new) always undoes to the same old id.\nfunction stepMap(aliases: readonly IdAlias[], direction: StepMap[\"direction\"]): StepMap {\n const byId = new Map<string, IdAlias>();\n const sorted = [...aliases].sort((a, b) => compare(a.oldId, b.oldId) || compare(a.newId, b.newId));\n for (const alias of sorted) {\n const key = direction === \"forward\" ? alias.oldId : alias.newId;\n if (!byId.has(key)) byId.set(key, alias);\n }\n return { direction, byId };\n}\n\nfunction compare(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\nfunction overallReason(hops: readonly IdAlias[]): IdAliasReason | undefined {\n if (hops.length === 0) return undefined;\n return hops.some((h) => h.reason === \"move\") ? \"move\" : hops[hops.length - 1]!.reason;\n}\n\n// One lookup per snapshot: a snapshot's aliases are one git diff, so A to B plus B to A is a swap, not a cycle.\nfunction walk(requestedId: string, maps: readonly StepMap[]): AliasResolution {\n let id = requestedId;\n const hops: IdAlias[] = [];\n for (const { direction, byId } of maps) {\n const alias = byId.get(id);\n if (!alias) continue;\n hops.push(alias);\n id = direction === \"forward\" ? alias.newId : alias.oldId;\n }\n return { requestedId, id, hops, reason: overallReason(hops) };\n}\n\nfunction chainSteps(input: AliasChainInput): { steps: LineageStep[]; connected: boolean } {\n if (input.from === null) return { steps: rootPath(input.lineage, input.to, input.maxHops), connected: true };\n const path = lineagePath(input.lineage, input.from, input.to, input.maxHops);\n if (path) return { steps: path, connected: true };\n return { steps: [{ snapshotId: input.to, direction: \"forward\" }], connected: false };\n}\n\n/** Carry node ids from one snapshot into another across every rename between them. */\nexport function createAliasChain(input: AliasChainInput): AliasChain {\n const { steps, connected } = chainSteps(input);\n const maps = steps.map((s) => stepMap(input.loadAliases(s.snapshotId), s.direction));\n const cache = new Map<string, AliasResolution>();\n const trace = (id: string): AliasResolution => {\n let hit = cache.get(id);\n if (!hit) cache.set(id, (hit = walk(id, maps)));\n return hit;\n };\n return { fromSnapshotId: input.from, toSnapshotId: input.to, connected, steps, resolve: (id) => trace(id).id, trace };\n}\n","import { detectGitHead, isGitAncestor, resolveGitRef } from \"../git-renames.js\";\nimport { rowToSnapshot, type SnapshotDbRow } from \"../rows.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { SnapshotRow } from \"../types.js\";\nimport { createAliasChain, type AliasChain, type AliasResolution } from \"./alias-chain.js\";\nimport { buildLineage, type Lineage } from \"./lineage.js\";\n\nexport interface AliasChainOptions {\n maxHops?: number;\n}\n\nexport interface ResolveAliasOptions extends AliasChainOptions {\n /** The snapshot the id was read in; omitted, the id may come from any ancestor of the target. */\n fromSnapshotId?: number;\n}\n\nexport interface PriorSnapshotOptions {\n /** Only snapshots older than this id count; omitted, every snapshot does. */\n before?: number;\n /** A git checkout to resolve `ref` in; without it only the snapshot's `ref` label matches. */\n repoRoot?: string;\n}\n\n// The store's listSnapshots caps at a limit; lineage needs every snapshot.\nfunction allSnapshots(store: CodeGraphStore): SnapshotRow[] {\n return (store.db.prepare(\"SELECT * FROM snapshot ORDER BY id\").all() as SnapshotDbRow[]).map(rowToSnapshot);\n}\n\n/** The alias-base tree over every snapshot in the store. */\nexport function loadLineage(store: CodeGraphStore): Lineage {\n return buildLineage(allSnapshots(store));\n}\n\n/** Carry node ids from `fromSnapshotId` into `toSnapshotId` through every alias between them, in either direction. */\nexport function aliasChain(\n store: CodeGraphStore,\n fromSnapshotId: number | null,\n toSnapshotId: number,\n options: AliasChainOptions = {},\n): AliasChain {\n return createAliasChain({\n lineage: loadLineage(store),\n loadAliases: (id) => store.listAliases(id),\n from: fromSnapshotId,\n to: toSnapshotId,\n maxHops: options.maxHops,\n });\n}\n\n/** Resolve an id to its form in `toSnapshotId`: `a.ts` renamed to `b.ts` then `c.ts` resolves to `c.ts`. */\nexport function resolveAlias(\n store: CodeGraphStore,\n id: string,\n toSnapshotId: number,\n options: ResolveAliasOptions = {},\n): AliasResolution {\n return aliasChain(store, options.fromSnapshotId ?? null, toSnapshotId, options).trace(id);\n}\n\n/**\n * The newest snapshot a ref denotes: first the snapshot of the commit git resolves\n * `ref` to (with `repoRoot`), else the newest snapshot whose `ref` label is `ref`.\n */\nexport function priorSnapshotForRef(\n store: CodeGraphStore,\n ref: string,\n options: PriorSnapshotOptions = {},\n): SnapshotRow | null {\n const before = options.before ?? Number.POSITIVE_INFINITY;\n const candidates = allSnapshots(store).filter((s) => s.id < before).reverse();\n const commit = options.repoRoot ? resolveGitRef(options.repoRoot, `${ref}^{commit}`) : null;\n const byCommit = commit ? candidates.find((s) => s.commitHash === commit) : undefined;\n return byCommit ?? candidates.find((s) => s.ref === ref) ?? null;\n}\n\n/** The commit a new snapshot is indexed at (default HEAD), in the checkout that can verify its history. */\nexport interface AliasTarget {\n repoRoot: string;\n commit?: string;\n}\n\n/** The commit an index of `target` records, or null outside a git checkout. */\nexport function aliasTargetCommit(target: AliasTarget): string | null {\n return target.commit ?? detectGitHead(target.repoRoot);\n}\n\n/**\n * The snapshot a new index of `ref` computes its aliases against: its own ref's newest\n * committed snapshot, else any, and only when that commit is an ancestor of `target`.\n */\nexport function aliasBaseFor(store: CodeGraphStore, ref: string, target: AliasTarget): SnapshotRow | null {\n const committed = allSnapshots(store).filter((s) => s.commitHash).reverse();\n const candidate = committed.find((s) => s.ref === ref) ?? committed[0];\n if (!candidate?.commitHash) return null;\n // A force-pushed ref can leave the candidate on an unrelated history, where a rename diff is noise.\n const commit = aliasTargetCommit(target);\n return commit && isGitAncestor(target.repoRoot, candidate.commitHash, commit) ? candidate : null;\n}\n","import { buildAliases, detectRenames } from \"../git-renames.js\";\nimport { SYMBOL_ID_SEP } from \"../extractors/ids.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { GraphNode, IdAlias } from \"../types.js\";\nimport { aliasBaseFor, aliasTargetCommit } from \"./store-identity.js\";\n\nexport interface AliasBridgeInput {\n rootDir: string;\n idRoot: string;\n ref: string;\n commitHash?: string;\n detectRenames?: boolean;\n nodes: ReadonlyMap<string, GraphNode>;\n}\n\n/** The snapshot a new snapshot's aliases start from, and the aliases themselves. */\nexport interface AliasBridge {\n baseSnapshotId: number | null;\n aliases: IdAlias[];\n}\n\n// `#` sorts directly before `$`, so this range is exactly the ids of one file's symbols.\nconst SYMBOLS_OF_FILE = `SELECT id FROM node\n WHERE snapshot_id = ? AND id >= ? AND id < ? AND kind = 'symbol'`;\n\nfunction symbolIdsOf(store: CodeGraphStore, snapshotId: number, fileId: string): string[] {\n const rows = store.db.prepare(SYMBOLS_OF_FILE).all(snapshotId, `${fileId}#`, `${fileId}$`) as { id: string }[];\n return rows.map((r) => r.id);\n}\n\n/**\n * Symbol aliases derived from file aliases, so `a.ts#Job.run` follows `a.ts` to\n * `b.ts#Job.run`. Only symbols present on both sides get one; a symbol renamed\n * inside the moved file is not followed.\n */\nexport function movedSymbolAliases(\n store: CodeGraphStore,\n baseSnapshotId: number,\n fileAliases: readonly IdAlias[],\n nodes: ReadonlyMap<string, GraphNode>,\n): IdAlias[] {\n const out: IdAlias[] = [];\n for (const alias of fileAliases) {\n if (nodes.get(alias.newId)?.kind !== \"file\") continue;\n for (const oldId of symbolIdsOf(store, baseSnapshotId, alias.oldId)) {\n const newId = alias.newId + SYMBOL_ID_SEP + oldId.slice(alias.oldId.length + 1);\n if (nodes.get(newId)?.kind === \"symbol\") out.push({ oldId, newId, reason: alias.reason });\n }\n }\n return out;\n}\n\nfunction renameAliases(input: AliasBridgeInput, baseCommit: string, target: string): IdAlias[] {\n if (input.detectRenames === false || target === baseCommit) return [];\n const pairs = detectRenames({ repoRoot: input.rootDir, fromCommit: baseCommit, toCommit: target });\n return buildAliases(input.idRoot, pairs);\n}\n\n/** File, module, and symbol aliases bridging a rename between the alias base's commit and this index. */\nexport function computeAliasBridge(store: CodeGraphStore, input: AliasBridgeInput): AliasBridge {\n const target = { repoRoot: input.rootDir, commit: input.commitHash };\n const base = aliasBaseFor(store, input.ref, target);\n const commit = base ? aliasTargetCommit(target) : null;\n if (!base?.commitHash || !commit) return { baseSnapshotId: null, aliases: [] };\n const fileAliases = renameAliases(input, base.commitHash, commit);\n const symbols = movedSymbolAliases(store, base.id, fileAliases, input.nodes);\n return { baseSnapshotId: base.id, aliases: [...fileAliases, ...symbols] };\n}\n","import * as path from \"node:path\";\nimport type { GraphNode, NodeRole } from \"./types.js\";\nimport { isGeneratedFile, loadGeneratedPatterns } from \"./generated.js\";\nimport { workingTreeSource, type IndexSource } from \"./index-source.js\";\nimport { parseRoleGlobs, roleGlobMatcher, type RoleGlobs } from \"./role-globs.js\";\n\nconst TEST_RE = /(?:^|\\/)(?:__tests__\\/|tests?\\/)|\\.(?:test|spec)(?:\\.[a-z]+)?$/;\n// The extension is optional so a story's module node (`Button.stories`) matches too.\nconst STORY_RE = /\\.stories(?:\\.[cm]?[jt]sx?)?$|\\.mdx$/;\nconst FIXTURE_RE = /(?:^|\\/)fixtures(?:\\/|$)/;\n// One-off tooling under scripts/ or dormant archive/ dirs: report noise, not\n// product signal. Test-ness wins (checked first) since it's more meaningful.\nconst SCRIPT_RE = /(?:^|\\/)(?:scripts|archive)(?:\\/|$)/;\nconst BARREL_RE = /(?:^|\\/)index(?:\\.[a-z]+)?$/;\nconst TYPES_RE = /(?:^|\\/)(?:[a-z][\\w-]*\\.)?types(?:\\.[a-z]+)?$/i;\nconst CONFIG_RE = /\\.config(?:\\.[a-z]+)?$/;\n\nexport const ALL_ROLES: readonly NodeRole[] = [\n \"test\",\n \"fixture\",\n \"story\",\n \"lab\",\n \"barrel\",\n \"types\",\n \"config\",\n \"script\",\n \"entry\",\n \"generated\",\n \"source\",\n];\n\nexport interface RoleHints {\n /** File begins with a `#!` shebang, i.e. it is an executable entry point. */\n hasShebang?: boolean;\n /** File is codegen output (`.gitattributes linguist-generated` or heuristic). */\n isGenerated?: boolean;\n /** Role a `.codewatch/roles.json` glob assigns this file. */\n configuredRole?: NodeRole;\n}\n\nexport function classifyRole(id: string, hints?: RoleHints): NodeRole {\n // Generated wins outright: codegen output is noise for every human-facing\n // signal, so labeling it `generated` (not, say, `barrel` for a `.gen` index)\n // is what lets hotspots/unused-exports exclude it at one shared boundary.\n if (hints?.isGenerated) return \"generated\";\n // A repo's own globs know its layout better than any naming heuristic.\n if (hints?.configuredRole) return hints.configuredRole;\n if (TEST_RE.test(id)) return \"test\";\n // The story filename convention wins over a fixtures/ or scripts/ directory.\n if (STORY_RE.test(id)) return \"story\";\n if (FIXTURE_RE.test(id)) return \"fixture\";\n if (SCRIPT_RE.test(id)) return \"script\";\n // A shebang-prefixed file (e.g. a CLI's index.ts) is an executable entry\n // point, not re-export plumbing — check before the filename barrel heuristic\n // so it doesn't get mislabeled as `barrel`. `entry` seeds reachability (like\n // a barrel) and is exempt from the fan-out smell (an entry legitimately wires\n // up many command modules).\n if (hints?.hasShebang) return \"entry\";\n if (BARREL_RE.test(id)) return \"barrel\";\n if (TYPES_RE.test(id)) return \"types\";\n if (CONFIG_RE.test(id)) return \"config\";\n return \"source\";\n}\n\nexport interface AnnotateRolesOptions {\n /** Node ids whose source begins with a `#!` shebang. */\n shebangIds?: ReadonlySet<string>;\n /** Node ids detected as generated (codegen output). */\n generatedIds?: ReadonlySet<string>;\n /** Configured role globs; see {@link loadRoleGlobs}. */\n roleGlobs?: RoleGlobs;\n}\n\nconst ROLE_GLOBS_PATH = \".codewatch/roles.json\";\n\n/** Read `<rootDir>/.codewatch/roles.json`; a repo without one configures no globs. */\nexport function loadRoleGlobs(\n rootDir: string,\n source: IndexSource = workingTreeSource(),\n): RoleGlobs {\n const file = path.join(rootDir, ROLE_GLOBS_PATH);\n if (!source.fileExists(file)) return {};\n return parseRoleGlobs(JSON.parse(source.readFile(file)), ROLE_GLOBS_PATH, ALL_ROLES);\n}\n\ninterface ReadFileLike {\n filePath: string;\n content: string;\n}\n\n/**\n * Derive per-file role hints for a batch of read files in one pass: the shebang\n * set (executable entries) and the generated set (codegen output, detected via\n * `.gitattributes linguist-generated` under `idRoot` plus filename/path\n * heuristics). Lives here so the indexer stays at its file-size ceiling.\n */\nexport function computeRoleHints(\n readFiles: readonly ReadFileLike[],\n idRoot: string,\n toId: (root: string, filePath: string) => string,\n source?: IndexSource,\n): AnnotateRolesOptions {\n const patterns = loadGeneratedPatterns(idRoot, source);\n const shebangIds = new Set<string>();\n const generatedIds = new Set<string>();\n for (const rf of readFiles) {\n const id = toId(idRoot, rf.filePath);\n if (rf.content.startsWith(\"#!\")) shebangIds.add(id);\n if (isGeneratedFile(id, patterns)) generatedIds.add(id);\n }\n return { shebangIds, generatedIds, roleGlobs: loadRoleGlobs(idRoot, source) };\n}\n\nexport function annotateRoles(\n nodes: readonly GraphNode[],\n options?: AnnotateRolesOptions,\n): GraphNode[] {\n const configuredRole = roleGlobMatcher(options?.roleGlobs, ALL_ROLES);\n return nodes.map((n) =>\n n.kind === \"file\" || n.kind === \"module\"\n ? {\n ...n,\n role:\n n.role ??\n classifyRole(n.id, {\n hasShebang: options?.shebangIds?.has(n.id) ?? false,\n isGenerated: options?.generatedIds?.has(n.id) ?? false,\n configuredRole: configuredRole(n.id),\n }),\n }\n : n,\n );\n}\n","import * as path from \"node:path\";\nimport { workingTreeSource, type IndexSource } from \"./index-source.js\";\n\n/**\n * Generated-code detection. Generated files (codegen output, e.g. an OpenAPI\n * `client.gen.ts`) churn and re-export in bulk, so they dominate hotspots and\n * unused-exports with noise that no human maintains. This module supplies one\n * reusable predicate — {@link isGeneratedFile} — used to mark such files so the\n * hotspot / unused-export surfaces can exclude them at their shared boundary.\n *\n * Detection has two tiers: the authoritative `.gitattributes linguist-generated`\n * markers a repo already declares, and a filename/path heuristic fallback for\n * repos that declare nothing.\n */\n\n// Fallback heuristic: `*.gen.*` / `*.generated.*` basenames and any path with a\n// `generated/` segment. Anchored to a segment boundary so `regenerated/` and a\n// stray `foogen.ts` don't match.\nconst HEURISTIC_FILE_RE = /(?:^|\\/)[^/]*\\.(?:gen|generated)\\.[^/]*$/;\nconst HEURISTIC_DIR_RE = /(?:^|\\/)generated\\//;\n\n/** True when a path looks generated by filename/dir convention alone. */\nexport function isGeneratedByHeuristic(id: string): boolean {\n return HEURISTIC_FILE_RE.test(id) || HEURISTIC_DIR_RE.test(id);\n}\n\n/**\n * A file is generated when it matches a repo-declared `linguist-generated`\n * pattern or the filename/path heuristic. `patterns` come from\n * {@link parseGeneratedPatterns}; pass `[]` when no `.gitattributes` exists.\n */\nexport function isGeneratedFile(\n id: string,\n patterns: readonly RegExp[],\n): boolean {\n for (const rx of patterns) if (rx.test(id)) return true;\n return isGeneratedByHeuristic(id);\n}\n\n/** Read `<rootDir>/.gitattributes` and compile its linguist-generated patterns. */\nexport function loadGeneratedPatterns(\n rootDir: string,\n source: IndexSource = workingTreeSource(),\n): RegExp[] {\n try {\n const content = source.readFile(path.join(rootDir, \".gitattributes\"));\n return parseGeneratedPatterns(content);\n } catch {\n return [];\n }\n}\n\ninterface GeneratedRule {\n readonly rx: RegExp;\n readonly generated: boolean;\n}\n\n/**\n * Parse `.gitattributes` text into regexes for every path pattern marked\n * `linguist-generated` (bare, or `=true`). Git applies the last matching line,\n * so a later `-linguist-generated` / `=false` / `!linguist-generated` line opts\n * a path back out: each returned regex excludes the opt-out patterns that\n * follow its line. Within one line the last attribute token wins.\n */\nexport function parseGeneratedPatterns(content: string): RegExp[] {\n const rules = parseGeneratedRules(content);\n const out: RegExp[] = [];\n rules.forEach((rule, i) => {\n if (!rule.generated) return;\n const optOuts = rules.slice(i + 1).filter((r) => !r.generated);\n out.push(excluding(rule.rx, optOuts.map((r) => r.rx)));\n });\n return out;\n}\n\nfunction parseGeneratedRules(content: string): GeneratedRule[] {\n const rules: GeneratedRule[] = [];\n for (const raw of content.split(\"\\n\")) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const parsed = /^(\"(?:[^\"\\\\]|\\\\.)*\"|\\S+)\\s*(.*)$/.exec(line);\n if (!parsed) continue;\n const generated = generatedAttr(parsed[2]!.split(/\\s+/).filter(Boolean));\n if (generated === undefined) continue;\n rules.push({ rx: gitattributesPatternToRegex(unquote(parsed[1]!)), generated });\n }\n return rules;\n}\n\n// Every pattern regex is anchored at both ends, so a lookahead over the\n// opt-out sources rejects exactly the ids a later line unsets.\nfunction excluding(rx: RegExp, optOuts: readonly RegExp[]): RegExp {\n if (optOuts.length === 0) return rx;\n const rejected = optOuts.map((o) => `(?:${o.source})`).join(\"|\");\n return new RegExp(`(?!${rejected})(?:${rx.source})`);\n}\n\n/** Resolve the effective linguist-generated value from a line's attribute tokens. */\nfunction generatedAttr(attrs: readonly string[]): boolean | undefined {\n let value: boolean | undefined;\n for (const a of attrs) {\n if (a === \"linguist-generated\" || a === \"linguist-generated=true\") value = true;\n else if (OPT_OUT_TOKENS.has(a)) value = false;\n }\n return value;\n}\n\nconst OPT_OUT_TOKENS = new Set([\n \"-linguist-generated\",\n \"linguist-generated=false\",\n \"!linguist-generated\",\n]);\n\nfunction unquote(token: string): string {\n return token.startsWith('\"') && token.endsWith('\"')\n ? token.slice(1, -1).replace(/\\\\(.)/g, \"$1\")\n : token;\n}\n\nconst NEVER_MATCHES = /(?!)/;\n\n/**\n * Convert a gitignore-style `.gitattributes` path pattern to a regex matched\n * against a repo-relative posix id: a slash-free pattern matches at any depth\n * (`*.gen.ts`), a leading or inner slash anchors to the root, a non-final `**`\n * segment matches zero or more directories, a final `**` segment matches\n * everything inside, and `*`/`?` stay within a segment. A trailing `/` matches\n * only a directory, never a path inside it (gitattributes(5)), so it matches\n * no file id. The result is anchored at both ends.\n */\nexport function gitattributesPatternToRegex(pattern: string): RegExp {\n let p = pattern;\n if (p.endsWith(\"/\")) return NEVER_MATCHES;\n const anchored = p.includes(\"/\");\n if (p.startsWith(\"/\")) p = p.slice(1);\n const prefix = anchored ? \"^\" : \"^(?:.*/)?\";\n return new RegExp(prefix + globBody(p) + \"$\");\n}\n\nfunction globBody(p: string): string {\n const segments = p.split(\"/\");\n return segments\n .map((seg, i) => {\n const last = i === segments.length - 1;\n if (seg === \"**\") return last ? \".+\" : \"(?:.*/)?\";\n return globSegment(seg) + (last ? \"\" : \"/\");\n })\n .join(\"\");\n}\n\nfunction globSegment(seg: string): string {\n let out = \"\";\n for (const c of seg) {\n if (c === \"*\") out += \"[^/]*\";\n else if (c === \"?\") out += \"[^/]\";\n else out += c.replace(/[.+(){}|^$\\\\[\\]]/, \"\\\\$&\");\n }\n return out;\n}\n","import { gitattributesPatternToRegex } from \"./generated.js\";\nimport type { NodeRole } from \"./types.js\";\n\n/**\n * Repo-configured role globs, read from `.codewatch/roles.json`. They label\n * paths no filename convention can (a design system's `lab/` playground is\n * too generic a directory name to guess), and they beat the built-in role\n * heuristics. Globs use `.gitattributes` syntax, matched against file ids.\n */\nexport type RoleGlobs = Partial<Record<NodeRole, string[]>>;\n\n/** Validate parsed roles.json: an object mapping known roles to string arrays. */\nexport function parseRoleGlobs(\n value: unknown,\n label: string,\n knownRoles: readonly NodeRole[],\n): RoleGlobs {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(`${label}: expected an object mapping roles to glob arrays`);\n }\n const out: RoleGlobs = {};\n for (const [role, globs] of Object.entries(value)) {\n if (!knownRoles.includes(role as NodeRole)) {\n throw new Error(`${label}: unknown role \"${role}\"`);\n }\n if (!Array.isArray(globs) || !globs.every((g) => typeof g === \"string\")) {\n throw new Error(`${label}: \"${role}\" must be an array of glob strings`);\n }\n out[role as NodeRole] = globs;\n }\n return out;\n}\n\n/** Compile role globs into a lookup; the first role in `order` with a matching glob wins. */\nexport function roleGlobMatcher(\n globs: RoleGlobs | undefined,\n order: readonly NodeRole[],\n): (id: string) => NodeRole | undefined {\n const compiled = order.flatMap((role) =>\n (globs?.[role] ?? []).map((g) => ({ role, rx: gitattributesPatternToRegex(g) })),\n );\n return (id) => compiled.find(({ rx }) => rx.test(id))?.role;\n}\n","import { readlinkSync, realpathSync, statSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { isExcludedDir, shouldIncludeFile } from \"@titan-design/code-parser\";\nimport { Project, type FileSystemHost, type RuntimeDirEntry } from \"ts-morph\";\nimport { detectGitToplevel } from \"./history/git.js\";\nimport { listTreeBlobs, readBlobs, resolveCommit } from \"./history/git-tree.js\";\nimport { overlayHost, type TreeAnswers } from \"./git-tree-host.js\";\nimport { workingTreeSource, type IndexSource } from \"./index-source.js\";\n\n// Everything the indexer, ts-morph or generated.ts may read in the repo; batched into one cat-file.\nconst READ_BY_INDEX = /\\.(?:[cm]?[jt]sx?|json|pyi?)$|(?:^|\\/)\\.gitattributes$/;\n// Matches the kernel's SYMLOOP_MAX: a longer chain of dangling links is a cycle.\nconst MAX_LINK_HOPS = 40;\n\nlet emptyHost: FileSystemHost | undefined;\n\n/**\n * ts-morph only treats its own `errors.FileNotFoundError` / `DirectoryNotFoundError`\n * as \"absent\", and does not export them; an empty in-memory host throws them for any path.\n */\nfunction missing(abs: string, kind: \"file\" | \"dir\"): never {\n emptyHost ??= new Project({ useInMemoryFileSystem: true }).getFileSystem();\n if (kind === \"file\") emptyHost.readFileSync(abs);\n else emptyHost.readDirSync(abs);\n throw new Error(`${abs} was expected to be missing`);\n}\n\nfunction linkTarget(abs: string): string | null {\n try {\n return path.resolve(path.dirname(abs), readlinkSync(abs));\n } catch {\n return null;\n }\n}\n\n/** `abs` relative to `root`, or null when it lies outside it; a name such as `..foo` is inside. */\nfunction relativeInside(root: string, abs: string): string | null {\n const rel = path.relative(root, abs);\n return rel === \"..\" || rel.startsWith(`..${path.sep}`) || path.isAbsolute(rel) ? null : rel;\n}\n\n/**\n * `abs` with its longest existing prefix resolved through realpath and the\n * missing rest appended, following dangling links. Only for paths outside the repo.\n */\nfunction canonicalize(abs: string, hops = 0): string {\n const rest: string[] = [];\n for (let at = path.resolve(abs); ; at = path.dirname(at)) {\n try {\n return path.join(realpathSync(at), ...rest.reverse());\n } catch {\n const target = hops < MAX_LINK_HOPS ? linkTarget(at) : null;\n if (target !== null) return canonicalize(path.join(target, ...rest.reverse()), hops + 1);\n if (path.dirname(at) === at) return path.resolve(abs);\n rest.push(path.basename(at));\n }\n }\n}\n\n/** Index of the first segment of `rel` naming a dir the walk never ingests (dist, build, node_modules, …), or -1. */\nfunction firstExcluded(rel: string, includeSelf: boolean): number {\n const segments = rel.split(path.sep);\n return (includeSelf ? segments : segments.slice(0, -1)).findIndex(isExcludedDir);\n}\n\ntype EntryKind = \"file\" | \"dir\" | \"link\";\n\n/**\n * Where a path's answer comes from. The path is resolved one component at a\n * time, as a checkout of the commit would resolve it: a component the commit\n * tracks is the commit's file, dir or symlink, whatever today's disk has there,\n * and a tracked symlink is followed through the target its blob records; any\n * other component is looked up on disk, following symlinks, so a workspace\n * link under node_modules lands in the tracked package it points at. Tracked\n * paths come from the commit; untracked build output beneath a tracked dir (a\n * gitignored dist/) and out-of-repo paths come from disk; any other in-repo path is absent.\n */\ninterface Location {\n origin: \"tree\" | \"disk\" | \"missing\";\n canonical: string;\n /** Repo-relative path of `canonical`; null outside the repo. */\n rel: string | null;\n}\n\n/** A commit's files and symlinks keyed by repo-relative path, content read once on first use. */\nclass CommitTree {\n private readonly oids = new Map<string, string>();\n private readonly links = new Map<string, string>();\n private readonly dirs = new Map<string, Map<string, EntryKind>>();\n private readonly canonical = new Map<string, string>();\n private contents: Map<string, string> | undefined;\n\n constructor(\n readonly root: string,\n commit: string,\n ) {\n for (const blob of listTreeBlobs(root, commit)) {\n const rel = blob.path.split(\"/\").join(path.sep);\n (blob.link ? this.links : this.oids).set(rel, blob.oid);\n this.addEntry(rel, blob.link ? \"link\" : \"file\");\n }\n }\n\n /** The one place an answer's origin is decided; every file, dir and realpath answer goes through it. */\n locate(abs: string, kind: \"file\" | \"dir\"): Location {\n return this.classify(this.resolve(path.resolve(abs), 0), kind);\n }\n\n private classify(canonical: string, kind: \"file\" | \"dir\"): Location {\n const rel = relativeInside(this.root, canonical);\n if (rel === null) return { origin: \"disk\", canonical, rel: null };\n const tracked = kind === \"file\" ? this.oids.has(rel) : this.dirs.has(rel);\n if (tracked) return { origin: \"tree\", canonical, rel };\n return { origin: this.ownsBuildOutput(rel, kind === \"dir\") ? \"disk\" : \"missing\", canonical, rel };\n }\n\n /**\n * Untracked build output a checkout would see on disk: under an excluded dir\n * whose parent the commit tracks, so `untracked/dist` is as absent as `untracked`.\n * A tracked symlink only lands here when its chain loops or dangles, and is then absent.\n */\n private ownsBuildOutput(rel: string, includeSelf: boolean): boolean {\n const at = firstExcluded(rel, includeSelf);\n if (at < 0 || this.links.has(rel)) return false;\n return this.dirs.has(rel.split(path.sep).slice(0, at).join(path.sep));\n }\n\n *files(): Generator<string> {\n for (const rel of this.oids.keys()) yield path.join(this.root, rel);\n }\n\n /** Children of a tracked dir by name, or undefined when the commit has no such dir. */\n children(rel: string): Map<string, EntryKind> | undefined {\n return this.dirs.get(rel);\n }\n\n read(rel: string): string {\n return this.blob(this.oids.get(rel)!);\n }\n\n /** Every link target joins the first batch: a checkout resolves links before it reads anything. */\n private blob(oid: string): string {\n this.contents ??= readBlobs(this.root, [\n ...[...this.oids].filter(([r]) => READ_BY_INDEX.test(r)).map(([, o]) => o),\n ...this.links.values(),\n ]);\n // A blob outside READ_BY_INDEX is rare enough to read on its own.\n if (!this.contents.has(oid)) this.contents.set(oid, readBlobs(this.root, [oid]).get(oid)!);\n return this.contents.get(oid)!;\n }\n\n private tracks(rel: string | null): boolean {\n return rel !== null && (this.oids.has(rel) || this.dirs.has(rel));\n }\n\n private resolve(abs: string, hops: number): string {\n const parent = path.dirname(abs);\n return parent === abs ? abs : this.step(this.resolve(parent, hops), path.basename(abs), hops);\n }\n\n /**\n * Every component of every path and link target passes through here, memoized\n * per path and hop budget: a link named many times in nested targets is followed\n * once per budget, and a chain cut short by the budget never answers for a shorter one.\n */\n private step(dir: string, name: string, hops: number): string {\n const key = `${hops}:${path.join(dir, name)}`;\n let resolved = this.canonical.get(key);\n if (resolved === undefined) {\n resolved = this.stepOnce(dir, name, hops);\n this.canonical.set(key, resolved);\n }\n return resolved;\n }\n\n /** Disk is never consulted for a component the commit tracks, a symlink included. */\n private stepOnce(dir: string, name: string, hops: number): string {\n const next = path.join(dir, name);\n const rel = relativeInside(this.root, next);\n if (this.tracks(rel)) return next;\n if (hops >= MAX_LINK_HOPS) return next;\n const linkOid = rel === null ? undefined : this.links.get(rel);\n if (linkOid !== undefined) return this.follow(dir, this.blob(linkOid), hops + 1) ?? next;\n const target = linkTarget(next);\n return target === null ? next : this.resolve(target, hops + 1);\n }\n\n /**\n * A tracked link's target walked one component at a time from `dir`, as a\n * checkout walks it: `..` leaves the dir actually reached, so `gone/..` dangles\n * (null) when `gone` is absent, where lexical normalisation would drop it.\n */\n private follow(dir: string, target: string, hops: number): string | null {\n let at = path.isAbsolute(target) ? path.parse(path.resolve(target)).root : dir;\n for (const name of target.split(\"/\")) {\n if (name === \"\" || name === \".\") continue;\n if (name !== \"..\") at = this.step(at, name, hops);\n else if (this.isDir(at)) at = path.dirname(at);\n else return null;\n }\n return at;\n }\n\n private isDir(canonical: string): boolean {\n const { origin } = this.classify(canonical, \"dir\");\n if (origin !== \"disk\") return origin === \"tree\";\n return statSync(canonical, { throwIfNoEntry: false })?.isDirectory() ?? false;\n }\n\n private addEntry(rel: string, kind: EntryKind): void {\n let child = rel;\n let childKind = kind;\n for (let dir = path.dirname(rel); child !== \".\"; child = dir, dir = path.dirname(dir)) {\n const key = dir === \".\" ? \"\" : dir;\n const known = this.dirs.has(key);\n const children = this.dirs.get(key) ?? new Map<string, EntryKind>();\n children.set(path.basename(child), childKind);\n this.dirs.set(key, children);\n if (known) return;\n childKind = \"dir\";\n }\n }\n}\n\n/** The tree's files under `rootDir` that `walkSourceFiles` would ingest from a checkout. */\nfunction* ingestedUnder(tree: CommitTree, rootDir: string, languages: readonly string[]): Generator<string> {\n for (const abs of tree.files()) {\n const rel = relativeInside(rootDir, abs);\n if (rel === null) continue;\n if (path.dirname(rel).split(path.sep).some(isExcludedDir)) continue;\n if (shouldIncludeFile(rel, [...languages])) yield abs;\n }\n}\n\nfunction listTreeFiles(tree: CommitTree, rootDirs: readonly string[], languages: readonly string[]): string[] {\n const seen = new Set<string>();\n for (const rootDir of rootDirs) {\n for (const abs of ingestedUnder(tree, rootDir, languages)) seen.add(abs);\n }\n return [...seen].sort();\n}\n\n/** Untracked build-output dirs on disk under a tracked dir, so a listing agrees with directoryExists. */\nfunction diskBuildDirs(real: FileSystemHost, canonical: string): RuntimeDirEntry[] {\n if (!real.directoryExistsSync(canonical)) return [];\n return real.readDirSync(canonical).filter((e) => e.isDirectory && isExcludedDir(path.basename(e.name)));\n}\n\ninterface Exists {\n file(abs: string): boolean;\n dir(abs: string): boolean;\n}\n\n/** A tracked entry as the real host reports it: a symlink is typed by what it resolves to. */\nfunction treeEntry(at: string, kind: EntryKind, exists: Exists): RuntimeDirEntry {\n if (kind !== \"link\") return { name: at, isFile: kind === \"file\", isDirectory: kind === \"dir\", isSymlink: false };\n return { name: at, isFile: exists.file(at), isDirectory: exists.dir(at), isSymlink: true };\n}\n\n/** Entries are named under the path as asked, as the real host names them. */\nfunction readDirAt(tree: CommitTree, real: FileSystemHost, abs: string, exists: Exists): RuntimeDirEntry[] {\n const at = tree.locate(abs, \"dir\");\n const asAsked = (entry: RuntimeDirEntry) => ({ ...entry, name: path.join(path.resolve(abs), path.basename(entry.name)) });\n if (at.origin === \"missing\") return missing(abs, \"dir\");\n if (at.origin === \"disk\") return real.readDirSync(at.canonical).map(asAsked);\n const entries = new Map<string, RuntimeDirEntry>();\n for (const [name, kind] of tree.children(at.rel!)!) {\n entries.set(name, treeEntry(path.join(path.resolve(abs), name), kind, exists));\n }\n for (const entry of diskBuildDirs(real, at.canonical)) {\n const name = path.basename(entry.name);\n if (!entries.has(name)) entries.set(name, asAsked(entry));\n }\n return [...entries.values()];\n}\n\nfunction treeAnswers(tree: CommitTree, real: FileSystemHost): TreeAnswers {\n const fileExists = (abs: string) => {\n const at = tree.locate(abs, \"file\");\n return at.origin === \"tree\" || (at.origin === \"disk\" && real.fileExistsSync(at.canonical));\n };\n const directoryExists = (abs: string) => {\n const at = tree.locate(abs, \"dir\");\n return at.origin === \"tree\" || (at.origin === \"disk\" && real.directoryExistsSync(at.canonical));\n };\n return {\n fileExists,\n readFile: (abs) => {\n const at = tree.locate(abs, \"file\");\n if (at.origin === \"tree\") return tree.read(at.rel!);\n return at.origin === \"disk\" ? real.readFileSync(at.canonical, \"utf-8\") : missing(abs, \"file\");\n },\n directoryExists,\n readDir: (abs) => readDirAt(tree, real, abs, { file: fileExists, dir: directoryExists }),\n // Like the real host, realpath of an absent path throws.\n realpath: (abs) =>\n fileExists(abs) || directoryExists(abs) ? tree.locate(abs, \"file\").canonical : missing(abs, \"file\"),\n };\n}\n\nfunction canonicalToplevel(repoRoot: string): string {\n const toplevel = detectGitToplevel(path.resolve(repoRoot));\n if (toplevel === null) throw new Error(`${repoRoot} is not inside a git repository`);\n return realpathSync(toplevel);\n}\n\n/**\n * Index `rev`'s tree from git objects, without a checkout and without writing to\n * the repo. Files keep their `<repo root>/<tree path>` absolute paths, so ids\n * match a working-tree index of the same commit. Workspace links into the repo\n * resolve to the commit; installed packages and untracked build output such as\n * a gitignored dist/ resolve against today's disk.\n */\nexport function gitTreeSource(repoRoot: string, rev: string): IndexSource {\n const canonicalRoot = canonicalToplevel(repoRoot);\n const { commit, commitEpoch } = resolveCommit(canonicalRoot, rev);\n const tree = new CommitTree(canonicalRoot, commit);\n const real = workingTreeSource().fileSystem;\n const answers = treeAnswers(tree, real);\n let fileSystem: FileSystemHost | undefined;\n return {\n listFiles: async (rootDirs, languages) => listTreeFiles(tree, rootDirs, languages),\n readFile: answers.readFile,\n // Like `existsSync` in the working-tree source, true for a dir as well as a file.\n fileExists: (abs) => answers.fileExists(abs) || answers.directoryExists(abs),\n get fileSystem() {\n fileSystem ??= overlayHost(answers, real);\n return fileSystem;\n },\n revision: { repoRoot: canonicalRoot, commit, commitEpoch },\n };\n}\n\n/**\n * An indexed dir in repo coordinates: the nearest ancestor that realpaths to the\n * repo root is rebased onto it and the rest kept as spelled, so a dir the commit\n * tracks is never resolved through today's symlinks or found missing on disk.\n */\nfunction rebaseOntoRoot(abs: string, repoRoot: string): string {\n const rest: string[] = [];\n for (let at = path.resolve(abs); path.dirname(at) !== at; at = path.dirname(at)) {\n if (realpathOrNull(at) === repoRoot) return path.join(repoRoot, ...rest.reverse());\n rest.push(path.basename(at));\n }\n return canonicalize(abs);\n}\n\nfunction realpathOrNull(abs: string): string | null {\n try {\n return realpathSync(abs);\n } catch {\n return null;\n }\n}\n\n/** Roots for indexing a revision: ids are rooted at the realpath'd repo root, and so is each indexed dir. */\nexport function rootsAtRevision(\n paths: readonly string[],\n revision: NonNullable<IndexSource[\"revision\"]>,\n): { rootDirs: string[]; idRoot: string } {\n const idRoot = realpathSync(revision.repoRoot);\n return { rootDirs: paths.map((p) => rebaseOntoRoot(p, idRoot)), idRoot };\n}\n","import type { FileSystemHost, RuntimeDirEntry } from \"ts-morph\";\n\nfunction readOnly(): never {\n throw new Error(\"a git tree source is read-only\");\n}\n\n/** One answer per path, shared by the IndexSource methods and the ts-morph host so they always agree. */\nexport interface TreeAnswers {\n fileExists(abs: string): boolean;\n readFile(abs: string): string;\n directoryExists(abs: string): boolean;\n readDir(abs: string): RuntimeDirEntry[];\n realpath(abs: string): string;\n}\n\n/** A read-only ts-morph host over a git tree source's answers. */\nexport function overlayHost(answers: TreeAnswers, real: FileSystemHost): FileSystemHost {\n return {\n isCaseSensitive: () => real.isCaseSensitive(),\n readDirSync: answers.readDir,\n readFileSync: (p) => answers.readFile(p),\n readFile: async (p) => answers.readFile(p),\n fileExistsSync: answers.fileExists,\n fileExists: async (p) => answers.fileExists(p),\n directoryExistsSync: answers.directoryExists,\n directoryExists: async (p) => answers.directoryExists(p),\n realpathSync: answers.realpath,\n getCurrentDirectory: () => real.getCurrentDirectory(),\n glob: () => Promise.reject(new Error(\"glob is not supported on a git tree source\")),\n globSync: () => readOnly(),\n delete: async () => readOnly(),\n deleteSync: readOnly,\n writeFile: async () => readOnly(),\n writeFileSync: readOnly,\n mkdir: async () => readOnly(),\n mkdirSync: readOnly,\n move: async () => readOnly(),\n moveSync: readOnly,\n copy: async () => readOnly(),\n copySync: readOnly,\n };\n}\n","import type { GraphEdge, GraphNode } from \"./types.js\";\n\n/** Edge weight (C-51 reference count), floored at 1 for unweighted edges. */\nexport function edgeWeight(e: GraphEdge): number {\n const w = (e.attrs as { weight?: number } | undefined)?.weight;\n return typeof w === \"number\" && w > 0 ? w : 1;\n}\n\n/**\n * Drop `references` edges (C-53) whose target `symbol` node doesn't exist — an\n * aliased re-export chain, or a barrel that changed under a reused file, can\n * resolve a name to an origin that doesn't declare it. `calls` edges (TP-323)\n * are dropped the same way, which is how a callee name that maps to no symbol\n * node is discarded rather than guessed. Only these two can dangle\n * (imports/re-exports resolve to always-emitted file/external nodes). Mutates\n * `edges` in place.\n */\nexport function pruneDanglingReferences(\n nodes: ReadonlyMap<string, GraphNode>,\n edges: Map<string, GraphEdge>,\n): void {\n for (const [key, edge] of edges) {\n const symbolLayer = edge.kind === \"references\" || edge.kind === \"calls\";\n if (symbolLayer && (!nodes.has(edge.dstId) || !nodes.has(edge.srcId))) edges.delete(key);\n }\n}\n\n/**\n * Resolve edges that land on a barrel (`role=\"barrel\"` — a bare `index.*`\n * re-export file) onto the files the barrel actually re-exports from, so\n * downstream signals measure the real dependency surface instead of the\n * re-export plumbing. A cross-package `import … from \"@codewatch/graph\"`\n * resolves to the barrel; without this every such import piles onto the barrel\n * as an artificial hub while the module that truly does the work is\n * under-credited.\n *\n * An inbound edge `F → B` (weight w) is split across B's outbound re-export\n * targets `t_i` in proportion to each target's re-export weight `r_i` (C-51:\n * the count of names B forwards from `t_i`). This CONSERVES w — no magnitude\n * inflation, unlike a uniform fan-out that turns one import into N edges — and\n * attributes it by how much of the barrel each target supplies. Resolution\n * recurses through barrel chains (a barrel re-exporting a barrel) with a\n * visited guard against re-export cycles; a barrel with no resolvable\n * re-exports is left as its own target so the dependency is never dropped.\n *\n * Pure over the assembled node/edge set, so it is deterministic regardless of\n * how much of an incremental index was reused.\n */\nexport function resolveBarrelEdges(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n): GraphEdge[] {\n const barrels = new Set<string>();\n for (const n of nodes) if (n.role === \"barrel\") barrels.add(n.id);\n if (barrels.size === 0) return [...edges];\n\n // Each barrel's outbound forwarding edges (re-exports, and any import it then\n // re-exports), keyed by barrel id, as {target, weight} to split inbound by.\n // A `references` edge is per-symbol *usage*, not re-export plumbing (a pure\n // barrel emits none — it only `export … from`s), so it's excluded from the\n // forwarding basis and kept as a real edge below (C-68).\n const forwards = new Map<string, { dst: string; weight: number }[]>();\n for (const e of edges) {\n if (!barrels.has(e.srcId) || e.kind === \"references\") continue;\n const arr = forwards.get(e.srcId) ?? [];\n arr.push({ dst: e.dstId, weight: edgeWeight(e) });\n forwards.set(e.srcId, arr);\n }\n\n const cache = new Map<string, Map<string, number>>();\n /** Distribution of a target over real (non-barrel) files: realId → fraction (sums to 1). */\n function resolve(id: string, seen: ReadonlySet<string>): Map<string, number> {\n if (!barrels.has(id)) return new Map([[id, 1]]);\n const cached = cache.get(id);\n if (cached) return cached;\n const targets = forwards.get(id);\n const total = targets?.reduce((s, t) => s + t.weight, 0) ?? 0;\n // Dead-end barrel (forwards nothing resolvable) or a cycle: keep as itself.\n if (!targets || total === 0 || seen.has(id)) return new Map([[id, 1]]);\n const out = new Map<string, number>();\n const nextSeen = new Set(seen).add(id);\n for (const t of targets) {\n const share = t.weight / total;\n for (const [real, frac] of resolve(t.dst, nextSeen)) {\n out.set(real, (out.get(real) ?? 0) + share * frac);\n }\n }\n cache.set(id, out);\n return out;\n }\n\n const resolved: GraphEdge[] = [];\n for (const e of edges) {\n // A barrel's own outbound import/re-export edges are plumbing — captured by\n // resolving its inbound edges to targets — so drop them to avoid\n // double-crediting. A `references` edge is genuine usage (e.g. a composition\n // root that the role classifier labels `barrel` but which actually consumes\n // a symbol via `const { runX } = await import(...)`, C-68), so keep it.\n if (barrels.has(e.srcId) && e.kind !== \"references\") continue;\n if (!barrels.has(e.dstId)) {\n resolved.push(e);\n continue;\n }\n const w = edgeWeight(e);\n for (const [real, frac] of resolve(e.dstId, new Set())) {\n if (real === e.srcId) continue; // a barrel that circles back to the importer\n resolved.push({\n ...e,\n dstId: real,\n attrs: { ...(e.attrs as object), weight: w * frac },\n });\n }\n }\n return resolved;\n}\n","import { createHash } from \"node:crypto\";\nimport type { Node } from \"web-tree-sitter\";\nimport { getLanguageFromPath, type ParsedFile } from \"@titan-design/code-parser\";\nimport type { CodeGraphStore } from \"./store.js\";\nimport { workingTreeSource, type IndexSource } from \"./index-source.js\";\nimport { fileId, parseSymbolId } from \"./extractors/ids.js\";\nimport { SOURCE_METRIC_NAMES } from \"./source-metrics.js\";\nimport { DEAD_CODE_METRIC_NAMES } from \"./analysis/dead-code.js\";\nimport { GROWTH_RISK_METRIC_NAMES } from \"./analysis/growth-risk.js\";\nimport { reconstructCosmetic, reconstructFragment } from \"./reconstruct.js\";\nimport type { Extractor } from \"@titan-design/code-parser\";\nimport type {\n FileFingerprint,\n GraphEdge,\n GraphFragment,\n GraphMetric,\n GraphNode,\n} from \"./types.js\";\n\n/** SHA-256 of file content. The fingerprint that gates per-file reuse. */\nexport function hashContent(content: string): string {\n return createHash(\"sha256\").update(content, \"utf8\").digest(\"hex\");\n}\n\n/**\n * Comment/whitespace-insensitive hash of a file's parse structure (C-18). Walks\n * the tree-sitter tree emitting each node's type plus leaf text, skipping comment\n * nodes; whitespace and positions are absent from the tree, so a pure reformat or\n * comment edit yields the SAME signature while any token change yields a new one.\n * Two files with an equal signature therefore produce identical edges and AST\n * metrics and differ only in line spans (and loc) — the COSMETIC reuse class.\n */\nexport function structuralSignature(file: ParsedFile): string {\n const parts: string[] = [];\n const visit = (node: Node): void => {\n if (node.type === \"comment\") return;\n parts.push(node.type);\n if (node.childCount === 0) parts.push(node.text);\n for (const child of node.children) if (child) visit(child);\n };\n visit(file.tree.rootNode);\n return hashContent(parts.join(\"\u001f\"));\n}\n\n/** The languages that have an extractor; anything else is skipped by the walk. */\nexport type SourceLanguage = \"typescript\" | \"python\";\n\nexport interface ReadFile {\n filePath: string;\n language: SourceLanguage;\n content: string;\n hash: string;\n}\n\nfunction sourceLanguage(filePath: string): SourceLanguage | null {\n const language = getLanguageFromPath(filePath);\n return language === \"typescript\" || language === \"python\" ? language : null;\n}\n\n/** Read + hash every source file. Cheap I/O; the parse/extract it gates is not. */\nexport async function readSourceFiles(\n filePaths: readonly string[],\n source: IndexSource = workingTreeSource(),\n): Promise<ReadFile[]> {\n const out: ReadFile[] = [];\n for (const filePath of filePaths) {\n const language = sourceLanguage(filePath);\n if (language === null) continue;\n const content = source.readFile(filePath);\n out.push({ filePath, language, content, hash: hashContent(content) });\n }\n return out;\n}\n\n/**\n * Split files into those to (re)parse and those reusable from the prior snapshot.\n * A file is reused when its content hash matches AND it is not in `affected` — the\n * set (C-20) whose edges a file-membership delta changed, which must re-extract\n * despite being byte-identical. `affected` is empty when membership is unchanged.\n */\nexport function classifyForReuse(\n readFiles: readonly ReadFile[],\n idRoot: string,\n reuse: ReuseBasis | null,\n affected: ReadonlySet<string> = new Set(),\n): { toParse: ReadFile[]; reusedFileIds: string[] } {\n const toParse: ReadFile[] = [];\n const reusedFileIds: string[] = [];\n for (const rf of readFiles) {\n const id = fileId(idRoot, rf.filePath);\n if (reuse && reuse.fingerprints.get(id) === rf.hash && !affected.has(id)) {\n reusedFileIds.push(id);\n } else {\n toParse.push(rf);\n }\n }\n return { toParse, reusedFileIds };\n}\n\n/** COSMETIC/structural split of the freshly-parsed files, plus every parsed and\n * reused file's structural signature (to persist for the next run). */\nexport interface ParsedClassification {\n /** Parsed files whose structure matches the basis — reuse edges, skip extract. */\n cosmeticFileIds: Set<string>;\n /** fileId → structural signature, for every parsed file and every reused file. */\n structuralByFileId: Map<string, string>;\n}\n\n/**\n * Split freshly-parsed files into COSMETIC (structure unchanged vs the basis —\n * only comments/whitespace moved) and STRUCTURAL (a real token change), by\n * comparing each file's structural signature against the basis (C-18). Also\n * carries reused (NONE-tier) files' signatures forward so they survive across\n * generations rather than decaying to NULL after their first reuse.\n */\nexport function classifyParsed(\n parsedByPath: Map<string, ParsedFile>,\n idRoot: string,\n reuse: ReuseBasis | null,\n reusedFileIds: readonly string[],\n affected: ReadonlySet<string> = new Set(),\n): ParsedClassification {\n const cosmeticFileIds = new Set<string>();\n const structuralByFileId = new Map<string, string>();\n for (const [filePath, parsed] of parsedByPath) {\n const id = fileId(idRoot, filePath);\n const sig = structuralSignature(parsed);\n structuralByFileId.set(id, sig);\n // A file affected by a membership delta (C-20) has a stale basis edge set even\n // though its structure is unchanged, so it must NOT take the cosmetic path.\n if (reuse && !affected.has(id) && reuse.structuralHashes.get(id) === sig) {\n cosmeticFileIds.add(id);\n }\n }\n if (reuse) {\n for (const id of reusedFileIds) {\n const sig = reuse.structuralHashes.get(id);\n if (sig !== undefined) structuralByFileId.set(id, sig);\n }\n }\n return { cosmeticFileIds, structuralByFileId };\n}\n\n/**\n * Build fragments for all files in walk order — extracting STRUCTURAL freshly-\n * parsed files, reconstructing NONE-tier reused ones, and (C-18) reconstructing\n * COSMETIC files from the basis edges while refreshing their symbol line spans\n * from the fresh parse, skipping the expensive ts-morph extract. Walk order is\n * preserved so the merge dedup resolves shared nodes identically to a full index.\n */\nexport function assembleFragments(input: {\n readFiles: readonly ReadFile[];\n idRoot: string;\n parsedByPath: Map<string, ParsedFile>;\n reuse: ReuseBasis | null;\n cosmeticFileIds: ReadonlySet<string>;\n extractor: Extractor<GraphFragment>;\n}): GraphFragment[] {\n const fragments: GraphFragment[] = [];\n for (const rf of input.readFiles) {\n const parsed = input.parsedByPath.get(rf.filePath);\n const id = fileId(input.idRoot, rf.filePath);\n if (parsed && input.reuse && input.cosmeticFileIds.has(id)) {\n fragments.push(\n reconstructCosmetic(input.idRoot, rf.filePath, id, input.reuse, parsed),\n );\n } else if (parsed) {\n fragments.push(...input.extractor.extract(parsed));\n } else if (input.reuse) {\n fragments.push(\n reconstructFragment(input.idRoot, rf.filePath, id, input.reuse),\n );\n }\n }\n return fragments;\n}\n\n/**\n * One fingerprint per file (content hash + C-18 structural signature), to persist\n * for the next run to diff against. The structural signature is looked up per\n * file; a file with none (e.g. a non-TS file, or a reuse carried from a pre-C-18\n * basis) stores NULL and simply can't take the cosmetic path next time.\n */\nexport function buildFingerprints(\n readFiles: readonly ReadFile[],\n idRoot: string,\n structuralByFileId: ReadonlyMap<string, string>,\n): FileFingerprint[] {\n return readFiles.map((rf) => {\n const id = fileId(idRoot, rf.filePath);\n return {\n fileId: id,\n contentHash: rf.hash,\n structuralHash: structuralByFileId.get(id),\n };\n });\n}\n\n/**\n * Everything from a prior snapshot needed to rebuild an unchanged file's\n * contribution to the graph without re-parsing it: its content fingerprint,\n * the node table (to look up external-node names), outbound edges grouped by\n * source file (a symbol's `calls` edges under the file declaring it), and the source-content metrics (loc, complexity, lcom4, ...).\n */\nexport interface ReuseBasis {\n snapshotId: number;\n fingerprints: Map<string, string>;\n /** Per-file structural signature (C-18); empty for a pre-C-18 basis. */\n structuralHashes: Map<string, string>;\n nodesById: Map<string, GraphNode>;\n edgesBySrc: Map<string, GraphEdge[]>;\n sourceMetricsByFile: Map<string, GraphMetric[]>;\n /** Symbol nodes grouped by their declaring file id, to carry forward for reused files (C-53). */\n symbolsByFile: Map<string, GraphNode[]>;\n}\n\n/**\n * Pick the most recent snapshot usable as a reuse basis: same index version and\n * carrying file fingerprints. Older snapshots predate the fingerprint table and\n * can't be diffed, so we return null and the caller does a full index.\n */\nexport function loadReuseBasis(\n db: CodeGraphStore,\n indexVersion: string,\n): ReuseBasis | null {\n for (const snap of db.listSnapshots({ limit: 50 })) {\n if (snap.indexVersion !== indexVersion) continue;\n const fingerprints = db.listFingerprints(snap.id);\n if (fingerprints.length === 0) continue;\n\n const nodesById = new Map<string, GraphNode>();\n const symbolsByFile = new Map<string, GraphNode[]>();\n // Opt into the symbol layer: reuse must carry symbol nodes and their inbound\n // reference edges forward for unchanged files (C-53).\n for (const n of db.listNodes(snap.id, { includeSymbols: true })) {\n nodesById.set(n.id, n);\n if (n.kind === \"symbol\" && n.parentId) {\n const bucket = symbolsByFile.get(n.parentId);\n if (bucket) bucket.push(n);\n else symbolsByFile.set(n.parentId, [n]);\n }\n }\n\n const edgesBySrc = new Map<string, GraphEdge[]>();\n for (const e of db.listEdges(snap.id, { includeReferences: true })) {\n // A `calls` edge leaves a symbol (TP-323); file it under the declaring file so reuse carries it.\n const fileKey = parseSymbolId(e.srcId)?.fileId ?? e.srcId;\n const bucket = edgesBySrc.get(fileKey);\n if (bucket) bucket.push(e);\n else edgesBySrc.set(fileKey, [e]);\n }\n\n const sourceMetricsByFile = new Map<string, GraphMetric[]>();\n for (const m of db.listMetrics(snap.id)) {\n // Source-content, dead-code, and growth-risk metrics are pure functions of\n // a file's bytes, so they carry forward verbatim for an unchanged file.\n if (\n !SOURCE_METRIC_NAMES.has(m.name) &&\n !DEAD_CODE_METRIC_NAMES.has(m.name) &&\n !GROWTH_RISK_METRIC_NAMES.has(m.name)\n )\n continue;\n // Per-symbol metrics (C-58) live on `<fileId>#<name>` nodes; bucket them\n // under their parent file so an unchanged file carries its symbol\n // complexity forward alongside its file-level source metrics.\n const node = nodesById.get(m.nodeId);\n const fileKey =\n node?.kind === \"symbol\" && node.parentId ? node.parentId : m.nodeId;\n const bucket = sourceMetricsByFile.get(fileKey);\n if (bucket) bucket.push(m);\n else sourceMetricsByFile.set(fileKey, [m]);\n }\n\n const structuralHashes = new Map<string, string>();\n for (const f of fingerprints) {\n if (f.structuralHash) structuralHashes.set(f.fileId, f.structuralHash);\n }\n\n return {\n snapshotId: snap.id,\n fingerprints: new Map(fingerprints.map((f) => [f.fileId, f.contentHash])),\n structuralHashes,\n nodesById,\n edgesBySrc,\n sourceMetricsByFile,\n symbolsByFile,\n };\n }\n return null;\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/**\n * Comment, docstring and code line counts for one function (TP-322). Lines are\n * counted as distinct source rows, so two comments on one row count once. The\n * docstring is documentation, not narration: it counts toward neither comment\n * nor body lines.\n */\nexport interface CommentLineStats {\n commentLines: number;\n docstringLines: number;\n bodyLines: number;\n commentRatio: number;\n}\n\n/** `fn` is the function node, `body` its body, `lines` the file's content split on newlines. */\nexport function commentLineStats(fn: Node, body: Node, lines: readonly string[]): CommentLineStats {\n const docstring = pythonDocstring(body);\n const comments = functionComments(fn, body);\n const commentLines = rowsOf(comments).size;\n const bodyLines = codeRows(body, docstring, comments, lines);\n return {\n commentLines,\n docstringLines: docstring ? rowSpan(docstring) : jsDocLines(fn),\n bodyLines,\n commentRatio: commentLines / Math.max(bodyLines, 1),\n };\n}\n\n/** The leading string statement of a Python block, which Python binds to `__doc__`. */\nexport function pythonDocstring(body: Node): Node | null {\n if (body.type !== \"block\") return null;\n const first = body.namedChildren.find((c) => c !== null && c.type !== \"comment\");\n if (first?.type !== \"expression_statement\" || first.namedChildCount !== 1) return null;\n return first.namedChildren[0]?.type === \"string\" ? first : null;\n}\n\n/** Statements of the body, docstring and comments aside; an expression-bodied arrow is its own statement. */\nexport function bodyStatements(body: Node, docstring: Node | null = pythonDocstring(body)): Node[] {\n if (body.type !== \"block\" && body.type !== \"statement_block\") return [body];\n return body.namedChildren.filter(\n (c): c is Node => c !== null && c.type !== \"comment\" && c.id !== docstring?.id,\n );\n}\n\n/** Python parses a block's leading comment as the block's sibling, so its comments are taken from the whole def after the signature. */\nexport function functionComments(fn: Node, body: Node): Node[] {\n if (body.type !== \"block\") return descendantsOfType(body, \"comment\");\n const signatureEnd = fn.childForFieldName(\"parameters\")?.endIndex ?? body.startIndex;\n return descendantsOfType(fn, \"comment\").filter((c) => c.startIndex >= signatureEnd);\n}\n\nexport function descendantsOfType(root: Node, type: string): Node[] {\n const out: Node[] = [];\n const visit = (node: Node): void => {\n if (node.type === type) out.push(node);\n for (const child of node.namedChildren) if (child) visit(child);\n };\n visit(root);\n return out;\n}\n\nfunction rowSpan(node: Node): number {\n return node.endPosition.row - node.startPosition.row + 1;\n}\n\nfunction rowsOf(nodes: readonly Node[]): Set<number> {\n const rows = new Set<number>();\n for (const n of nodes) {\n for (let r = n.startPosition.row; r <= n.endPosition.row; r++) rows.add(r);\n }\n return rows;\n}\n\n/** Rows under the body's statements that still hold code once comments are blanked out. */\nfunction codeRows(body: Node, docstring: Node | null, comments: readonly Node[], lines: readonly string[]): number {\n let count = 0;\n for (const row of rowsOf(bodyStatements(body, docstring))) {\n if (codeOnRow(row, lines[row] ?? \"\", comments).trim() !== \"\") count++;\n }\n return count;\n}\n\nfunction codeOnRow(row: number, text: string, comments: readonly Node[]): string {\n let out = text;\n for (const c of comments) {\n if (row < c.startPosition.row || row > c.endPosition.row) continue;\n const from = row === c.startPosition.row ? c.startPosition.column : 0;\n const to = row === c.endPosition.row ? c.endPosition.column : out.length;\n out = out.slice(0, from) + \" \".repeat(Math.max(to - from, 0)) + out.slice(to);\n }\n return out;\n}\n\n/** A `/** … *\\/` block ending on the row above the declaration, or on its first row. */\nfunction jsDocLines(fn: Node): number {\n const anchor = declarationAnchor(fn);\n const prev = anchor.previousNamedSibling;\n if (prev?.type !== \"comment\" || !prev.text.startsWith(\"/**\")) return 0;\n const gap = anchor.startPosition.row - prev.endPosition.row;\n return gap === 0 || gap === 1 ? rowSpan(prev) : 0;\n}\n\n/** The node a JSDoc block sits beside: the `const` or `export` wrapping a function, not the function itself. */\nfunction declarationAnchor(fn: Node): Node {\n let anchor = fn;\n if (fn.parent?.type === \"variable_declarator\") anchor = fn.parent.parent ?? fn;\n while (anchor.parent?.type === \"export_statement\") anchor = anchor.parent;\n return anchor;\n}\n","import type { Node } from \"web-tree-sitter\";\nimport { functionComments } from \"./comment-lines.js\";\n\n/**\n * Narrating comments (TP-322): a comment inside a function body that restates\n * the statement right after it, such as `// increment the retry count` above\n * `retryCount += 1`. A candidate signal, not a verdict: the match is a plain\n * token overlap, deterministic and cheap.\n */\n\nconst MIN_SHARED = 2;\nconst MIN_SHARE_OF_COMMENT = 0.5;\n\nconst STOPWORDS = new Set([\n \"the\", \"and\", \"for\", \"this\", \"that\", \"with\", \"from\", \"into\", \"then\", \"else\", \"when\", \"not\",\n \"are\", \"was\", \"has\", \"have\", \"its\", \"our\", \"all\", \"any\", \"can\", \"will\", \"just\", \"now\",\n \"return\", \"const\", \"let\", \"var\", \"def\", \"self\", \"none\", \"true\", \"false\", \"null\", \"undefined\",\n \"new\", \"await\", \"async\", \"function\",\n]);\n\nconst IDENTIFIER_TYPES = new Set([\n \"identifier\",\n \"property_identifier\",\n \"shorthand_property_identifier\",\n \"type_identifier\",\n]);\n\nexport function countNarratingComments(fn: Node, body: Node): number {\n let count = 0;\n for (const comment of functionComments(fn, body)) {\n const target = trailedStatement(comment) ?? nextStatement(comment);\n if (target && narrates(comment.text, target)) count++;\n }\n return count;\n}\n\n/** A comment on the same row as the end of the statement before it describes that statement. */\nfunction trailedStatement(comment: Node): Node | null {\n const prev = comment.previousNamedSibling;\n if (!prev || prev.type === \"comment\") return null;\n return prev.endPosition.row === comment.startPosition.row ? prev : null;\n}\n\n/** Lowercased word tokens of length 3 or more, split on non-word characters, underscores and camelCase humps. */\nexport function identifierTokens(text: string): Set<string> {\n const words = text.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\").split(/[^A-Za-z0-9]+/);\n const out = new Set<string>();\n for (const w of words) {\n const t = w.toLowerCase();\n if (t.length >= 3 && !STOPWORDS.has(t)) out.add(t);\n }\n return out;\n}\n\n/** A run of comment rows describes the first statement below it, inside the block a Python comment sits beside. */\nfunction nextStatement(comment: Node): Node | null {\n let next = comment.nextNamedSibling;\n while (next?.type === \"comment\") next = next.nextNamedSibling;\n if (next?.type !== \"block\") return next;\n return next.namedChildren.find((c) => c !== null && c.type !== \"comment\") ?? null;\n}\n\nfunction narrates(commentText: string, statement: Node): boolean {\n const said = identifierTokens(commentText);\n if (said.size === 0) return false;\n const code = identifierTokens(statementIdentifiers(statement).join(\" \"));\n let shared = 0;\n for (const t of said) if (code.has(t)) shared++;\n return shared >= MIN_SHARED || shared / said.size >= MIN_SHARE_OF_COMMENT;\n}\n\nfunction statementIdentifiers(statement: Node): string[] {\n const out: string[] = [];\n const visit = (node: Node): void => {\n if (IDENTIFIER_TYPES.has(node.type)) out.push(node.text);\n for (const child of node.namedChildren) if (child) visit(child);\n };\n visit(statement);\n return out;\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { GraphMetric } from \"../types.js\";\nimport { bodyStatements, descendantsOfType } from \"./comment-lines.js\";\nimport { identifierTokens } from \"./narrating-comments.js\";\n\n/**\n * Exception-handling metrics (TP-322), pure functions of one file's bytes. A\n * handler is swallowed when all it does is nothing, skip, bail out empty, or\n * log: the error stops here and no caller learns of it. Written on every file,\n * zeros included, so percentiles over a snapshot see the clean files too.\n */\nexport const EXCEPTION_METRIC_NAMES: readonly string[] = [\"except_count\", \"except_density\", \"swallowed_except\"];\n\nconst HANDLER_TYPES = [\"except_clause\", \"except_group_clause\", \"catch_clause\"];\nconst SILENT_STATEMENTS = new Set([\"pass_statement\", \"continue_statement\", \"empty_statement\"]);\nconst EMPTY_VALUES = new Set([\"None\", \"null\", \"undefined\"]);\nconst LOGGING_TOKENS = new Set([\"log\", \"logger\", \"logging\", \"warn\", \"warning\", \"warnings\", \"print\", \"console\"]);\nconst EXCEPT_CLAUSE_TYPES = new Set([\"except_clause\", \"except_group_clause\"]);\nconst OPTIONAL_IMPORT_EXCEPT_TYPES = new Set([\"ImportError\", \"ModuleNotFoundError\"]);\n\nexport function exceptionMetrics(nodeId: string, root: Node, loc: number): GraphMetric[] {\n const handlers = HANDLER_TYPES.flatMap((type) => descendantsOfType(root, type));\n const swallowed = handlers.filter((h) => isSwallowed(h)).length;\n return [\n { nodeId, name: \"except_count\", value: handlers.length, unit: \"count\" },\n { nodeId, name: \"except_density\", value: loc === 0 ? 0 : (handlers.length * 100) / loc, unit: \"per100loc\" },\n { nodeId, name: \"swallowed_except\", value: swallowed, unit: \"count\" },\n ];\n}\n\nfunction isSwallowed(handler: Node): boolean {\n if (isOptionalImportExcept(handler)) return false;\n const body = handler.childForFieldName(\"body\") ?? handler.namedChildren.find((c) => c?.type === \"block\");\n if (!body) return false;\n const statements = bodyStatements(body, null);\n if (statements.length === 0) return true;\n return statements.length === 1 && isSilent(statements[0]!);\n}\n\n/**\n * True for `except ImportError`, `except ModuleNotFoundError`, or a tuple of only\n * those two (with an optional `as name`) — the standard optional-dependency idiom,\n * never counted as swallowed regardless of what the body does.\n */\nfunction isOptionalImportExcept(handler: Node): boolean {\n if (!EXCEPT_CLAUSE_TYPES.has(handler.type)) return false;\n const value = handler.childForFieldName(\"value\");\n if (!value) return false;\n const typeExpr = value.type === \"as_pattern\" ? value.namedChild(0) : value;\n if (!typeExpr) return false;\n if (typeExpr.type === \"identifier\") return OPTIONAL_IMPORT_EXCEPT_TYPES.has(typeExpr.text);\n if (typeExpr.type !== \"tuple\") return false;\n const names = typeExpr.namedChildren.filter((c): c is Node => c !== null);\n return names.length > 0 && names.every((n) => n.type === \"identifier\" && OPTIONAL_IMPORT_EXCEPT_TYPES.has(n.text));\n}\n\nfunction isSilent(statement: Node): boolean {\n if (SILENT_STATEMENTS.has(statement.type)) return true;\n const value = statement.namedChildren[0];\n if (statement.type === \"return_statement\") return !value || EMPTY_VALUES.has(value.text);\n if (statement.type !== \"expression_statement\" || !value) return false;\n if (value.type === \"ellipsis\") return true;\n return isLoggingCall(value);\n}\n\nfunction isLoggingCall(node: Node): boolean {\n if (node.type !== \"call\" && node.type !== \"call_expression\") return false;\n const callee = node.childForFieldName(\"function\");\n if (!callee) return false;\n for (const token of identifierTokens(callee.text)) if (LOGGING_TOKENS.has(token)) return true;\n return false;\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/**\n * True for a JSX node that renders an element. A fragment (`<>…</>`) parses as a\n * `jsx_element` whose opening tag has no name, and adds no depth because it renders no node.\n */\nfunction rendersElement(node: Node): boolean {\n if (node.type === \"jsx_self_closing_element\") return true;\n if (node.type !== \"jsx_element\") return false;\n return node.childForFieldName(\"open_tag\")?.childForFieldName(\"name\") != null;\n}\n\n/**\n * Deepest chain of rendered JSX elements under `root`, root included (C-97 S1). The walk\n * continues through `jsx_expression` containers and inline callbacks, so\n * `rows.map(r => <Row/>)` inside `<tbody>` nests under it, and JSX in an attribute sits one\n * below its owning element. It does not descend into a child where `opensFunction` holds:\n * that function is measured on its own.\n */\nexport function jsxDepthOf(root: Node, opensFunction: (node: Node) => boolean): number {\n let max = 0;\n const visit = (node: Node, depth: number): void => {\n const own = rendersElement(node) ? depth + 1 : depth;\n if (own > max) max = own;\n for (const child of node.namedChildren) {\n if (child && !opensFunction(child)) visit(child, own);\n }\n };\n visit(root, 0);\n return max;\n}\n","import type { Node } from \"web-tree-sitter\";\nimport { TS_BOUND_FUNCTION_TYPES, TS_FUNCTION_DECL_TYPES } from \"./scope-path.js\";\n\n/**\n * Cognitive complexity per Sonarsource (\"Cognitive Complexity: A new way of\n * measuring understandability\"). Compared to cyclomatic, this:\n *\n * - Doesn't grow per `case` in a switch — the switch counts once.\n * - Adds a nesting bonus: nested control structures cost more than flat ones.\n * - Treats `else if` chains as one increment each, not as nested ifs.\n *\n * Returns the score for a function body. Caller drives the per-function loop.\n */\nexport function cognitiveComplexityOf(body: Node, language: string): number {\n const handler = language === \"python\" ? PY_HANDLER : TS_HANDLER;\n return scoreNode(body, 0, handler);\n}\n\ninterface LanguageHandler {\n /** Returns the nesting-charged increment (+1 + nesting), or 0 if the node\n * isn't a complexity contributor. */\n structuralIncrement: (node: Node, nesting: number) => number;\n /** True if this node increases nesting depth for its descendants. */\n isNesting: (node: Node) => boolean;\n /** Flat +1 increments (no nesting bonus): logical operators, `else`, etc. */\n flatIncrement: (node: Node) => number;\n}\n\nconst TS_STRUCTURAL = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_statement\",\n \"catch_clause\",\n \"ternary_expression\",\n]);\n\nconst PY_STRUCTURAL = new Set([\n \"if_statement\",\n \"for_statement\",\n \"while_statement\",\n \"except_clause\",\n \"conditional_expression\",\n // elif_clause is intentionally NOT here — it's a flat continuation of an\n // existing if (counted in flatIncrement). Including it would charge both\n // a structural and a flat +1.\n]);\n\nconst TS_NESTING = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_statement\",\n \"catch_clause\",\n ...TS_FUNCTION_DECL_TYPES,\n ...TS_BOUND_FUNCTION_TYPES,\n]);\n\nconst PY_NESTING = new Set([\n \"if_statement\",\n \"for_statement\",\n \"while_statement\",\n \"except_clause\",\n \"function_definition\",\n \"lambda\",\n]);\n\nconst TS_HANDLER: LanguageHandler = {\n structuralIncrement(node, nesting) {\n return TS_STRUCTURAL.has(node.type) ? 1 + nesting : 0;\n },\n isNesting(node) {\n return TS_NESTING.has(node.type);\n },\n flatIncrement(node) {\n if (node.type === \"else_clause\") return 1;\n if (\n node.type === \"binary_expression\" &&\n isLogicalOp(node) &&\n !isInnerOfSameOpChain(node, \"binary_expression\")\n ) {\n return 1;\n }\n return 0;\n },\n};\n\nconst PY_HANDLER: LanguageHandler = {\n structuralIncrement(node, nesting) {\n return PY_STRUCTURAL.has(node.type) ? 1 + nesting : 0;\n },\n isNesting(node) {\n return PY_NESTING.has(node.type);\n },\n flatIncrement(node) {\n if (node.type === \"elif_clause\" || node.type === \"else_clause\") return 1;\n if (\n node.type === \"boolean_operator\" &&\n !isInnerOfSameOpChain(node, \"boolean_operator\")\n ) {\n return 1;\n }\n return 0;\n },\n};\n\nfunction isLogicalOp(node: Node): boolean {\n const op = node.childForFieldName(\"operator\");\n return !!op && (op.text === \"&&\" || op.text === \"||\");\n}\n\n/**\n * Per Sonarsource: a sequence of like binary logical operators counts once,\n * not per occurrence. `a && b && c` is one chain (+1), not two (+2). Skip\n * the increment when this node's operator matches its parent's operator —\n * the outer node already counted the chain.\n */\nfunction isInnerOfSameOpChain(node: Node, parentType: string): boolean {\n const parent = node.parent;\n if (!parent || parent.type !== parentType) return false;\n const op = node.childForFieldName(\"operator\")?.text;\n const parentOp = parent.childForFieldName(\"operator\")?.text;\n return !!op && op === parentOp;\n}\n\n/**\n * A nested if under an else_clause is part of an `else if` chain — the\n * else_clause already counted +1, and treating it as a nested if would\n * double-charge AND inflate the nesting bonus. Skip both.\n */\nfunction isElseIf(node: Node): boolean {\n if (node.type !== \"if_statement\" && node.type !== \"elif_clause\") return false;\n const parent = node.parent;\n return !!parent && parent.type === \"else_clause\";\n}\n\nfunction scoreNode(\n node: Node,\n nesting: number,\n handler: LanguageHandler,\n): number {\n const elseIf = isElseIf(node);\n const structural = elseIf ? 0 : handler.structuralIncrement(node, nesting);\n const flat = handler.flatIncrement(node);\n const childNesting =\n !elseIf && handler.isNesting(node) ? nesting + 1 : nesting;\n\n let score = structural + flat;\n for (const child of node.namedChildren) {\n if (child) score += scoreNode(child, childNesting, handler);\n }\n return score;\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport { TS_CLASS_TYPES } from \"./scope-path.js\";\nimport type { GraphMetric } from \"./types.js\";\n\n/**\n * Lack of Cohesion of Methods, LCOM4 variant: count connected components\n * in the graph where each method is a node and two methods are linked when\n * they share at least one `this.<x>` (or `self.<x>`) reference or one calls\n * the other. LCOM4=1 → cohesive class; LCOM4>1 → the class could be split.\n *\n * Static methods and constructors are excluded (they don't bind to `this`).\n * Files with no classes emit no metrics. Files with classes emit\n * `lcom4_max` (max LCOM4 across classes in the file) and `class_count`.\n */\nexport function computeLcomMetrics(\n file: ParsedFile,\n fileId: string,\n): GraphMetric[] {\n const classes = collectClasses(file);\n if (classes.length === 0) return [];\n const out: GraphMetric[] = [\n {\n nodeId: fileId,\n name: \"class_count\",\n value: classes.length,\n unit: \"count\",\n },\n ];\n const scores = classes\n .map((c) => lcom4OfClass(c, file.language))\n .filter((s): s is number => s !== null);\n if (scores.length > 0) {\n out.push({\n nodeId: fileId,\n name: \"lcom4_max\",\n value: Math.max(...scores),\n unit: \"count\",\n });\n }\n return out;\n}\n\nfunction collectClasses(file: ParsedFile): Node[] {\n const isClass =\n file.language === \"python\"\n ? (n: Node) => n.type === \"class_definition\"\n : (n: Node) => TS_CLASS_TYPES.has(n.type);\n const out: Node[] = [];\n const visit = (node: Node): void => {\n if (isClass(node)) out.push(node);\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(file.tree.rootNode);\n return out;\n}\n\ninterface MethodInfo {\n name: string;\n usedNames: Set<string>;\n}\n\nfunction lcom4OfClass(classNode: Node, language: string): number | null {\n const methods = collectMethods(classNode, language);\n if (methods.length === 0) return null;\n if (methods.length === 1) return 1;\n return countComponents(methods);\n}\n\nfunction collectMethods(classNode: Node, language: string): MethodInfo[] {\n return language === \"python\"\n ? collectPythonMethods(classNode)\n : collectTsMethods(classNode);\n}\n\nfunction collectTsMethods(classNode: Node): MethodInfo[] {\n const body = classNode.childForFieldName(\"body\");\n if (!body) return [];\n const out: MethodInfo[] = [];\n for (const child of body.namedChildren) {\n if (!child || child.type !== \"method_definition\") continue;\n if (hasStaticModifier(child)) continue;\n const name = methodName(child);\n if (!name || name === \"constructor\") continue;\n out.push({ name, usedNames: thisRefs(child, \"this\") });\n }\n return out;\n}\n\nfunction collectPythonMethods(classNode: Node): MethodInfo[] {\n const body = classNode.childForFieldName(\"body\");\n if (!body) return [];\n const out: MethodInfo[] = [];\n for (const child of body.namedChildren) {\n const fn = child ? pythonMethodNode(child) : null;\n if (!fn) continue;\n const name = fn.childForFieldName(\"name\")?.text;\n if (!name || name === \"__init__\") continue;\n out.push({ name, usedNames: thisRefs(fn, \"self\") });\n }\n return out;\n}\n\n/** The `function_definition` a class-body statement declares, unwrapping decorators; null for static and class methods. */\nfunction pythonMethodNode(stmt: Node): Node | null {\n if (stmt.type === \"function_definition\") return stmt;\n if (stmt.type !== \"decorated_definition\") return null;\n if (isPythonStaticOrClassMethod(stmt)) return null;\n const def = stmt.childForFieldName(\"definition\");\n return def?.type === \"function_definition\" ? def : null;\n}\n\nfunction methodName(methodNode: Node): string | null {\n const nameNode = methodNode.childForFieldName(\"name\");\n return nameNode?.text ?? null;\n}\n\nfunction hasStaticModifier(methodNode: Node): boolean {\n for (const child of methodNode.children) {\n if (child?.type === \"static\") return true;\n }\n return false;\n}\n\nfunction isPythonStaticOrClassMethod(decorated: Node): boolean {\n return decorated.namedChildren.some(\n (c) =>\n c?.type === \"decorator\" &&\n (c.text === \"@staticmethod\" || c.text === \"@classmethod\"),\n );\n}\n\nfunction thisRefs(methodNode: Node, selfKeyword: string): Set<string> {\n const out = new Set<string>();\n const visit = (n: Node): void => {\n collectThisRef(n, selfKeyword, out);\n for (const child of n.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(methodNode);\n return out;\n}\n\nfunction collectThisRef(\n n: Node,\n selfKeyword: string,\n out: Set<string>,\n): void {\n if (n.type === \"member_expression\" || n.type === \"attribute\") {\n const obj = n.childForFieldName(\"object\");\n if (!obj) return;\n if (matchesSelf(obj, selfKeyword)) {\n const prop =\n n.childForFieldName(\"property\") ?? n.childForFieldName(\"attribute\");\n if (prop) out.add(prop.text);\n }\n }\n}\n\nfunction matchesSelf(node: Node, selfKeyword: string): boolean {\n if (selfKeyword === \"this\") return node.type === \"this\";\n return node.type === \"identifier\" && node.text === selfKeyword;\n}\n\nfunction countComponents(methods: readonly MethodInfo[]): number {\n const n = methods.length;\n const parent = Array.from({ length: n }, (_, i) => i);\n const find = (i: number): number => {\n while (parent[i]! !== i) {\n parent[i] = parent[parent[i]!]!;\n i = parent[i]!;\n }\n return i;\n };\n const union = (a: number, b: number): void => {\n const ra = find(a);\n const rb = find(b);\n if (ra !== rb) parent[ra] = rb;\n };\n for (let i = 0; i < n; i++) {\n for (let j = i + 1; j < n; j++) {\n if (areLinked(methods[i]!, methods[j]!)) union(i, j);\n }\n }\n const roots = new Set<number>();\n for (let i = 0; i < n; i++) roots.add(find(i));\n return roots.size;\n}\n\nfunction areLinked(a: MethodInfo, b: MethodInfo): boolean {\n if (a.usedNames.has(b.name)) return true;\n if (b.usedNames.has(a.name)) return true;\n for (const name of a.usedNames) {\n if (b.usedNames.has(name)) return true;\n }\n return false;\n}\n","import type { Node } from \"web-tree-sitter\";\nimport { bodyStatements } from \"./comment-lines.js\";\n\n/**\n * Pass-through functions (TP-322): the body is one call that forwards every\n * parameter, in order, as a bare argument, as in `def load(path): return read(path)`.\n * Only the exact case is claimed; a keyword argument, a reordering, a dropped or\n * transformed parameter, or a function with no parameters at all is not a pass-through.\n */\n\nconst RECEIVERS = new Set([\"self\", \"cls\"]);\nconst CALL_TYPES = new Set([\"call\", \"call_expression\"]);\nconst WRAPPER_TYPES = new Set([\"return_statement\", \"expression_statement\"]);\nconst PY_NAMED_PARAMS = new Set([\"default_parameter\", \"typed_default_parameter\"]);\nconst PY_SEPARATORS = new Set([\"keyword_separator\", \"positional_separator\"]);\n\nexport function isPassThrough(fn: Node, body: Node): boolean {\n const call = soleCall(body);\n if (!call) return false;\n const params = parameterShapes(fn);\n if (!params || params.length === 0) return false;\n const args = argumentShapes(call);\n return args !== null && args.length === params.length && args.every((a, i) => a === params[i]);\n}\n\nfunction soleCall(body: Node): Node | null {\n const statements = bodyStatements(body);\n if (statements.length !== 1) return null;\n const only = statements[0]!;\n if (CALL_TYPES.has(only.type)) return only;\n if (!WRAPPER_TYPES.has(only.type) || only.namedChildCount !== 1) return null;\n const value = only.namedChildren[0]!;\n return CALL_TYPES.has(value.type) ? value : null;\n}\n\n/** Each parameter as the argument text that forwards it (`a`, `*args`, `...rest`), or null when one cannot be forwarded bare. */\nfunction parameterShapes(fn: Node): string[] | null {\n const bare = fn.childForFieldName(\"parameter\");\n if (bare) return [bare.text];\n const list = fn.childForFieldName(\"parameters\");\n if (!list) return null;\n const shapes: string[] = [];\n for (const p of list.namedChildren) {\n if (!p || p.type === \"comment\" || PY_SEPARATORS.has(p.type)) continue;\n const shape = parameterShape(p);\n if (shape === null) return null;\n shapes.push(shape);\n }\n return RECEIVERS.has(shapes[0] ?? \"\") ? shapes.slice(1) : shapes;\n}\n\nfunction parameterShape(p: Node): string | null {\n if (p.type === \"identifier\") return p.text;\n if (p.type === \"list_splat_pattern\" || p.type === \"dictionary_splat_pattern\") return p.text;\n if (PY_NAMED_PARAMS.has(p.type)) return p.childForFieldName(\"name\")?.text ?? null;\n if (p.type === \"typed_parameter\") return parameterShape(p.namedChildren[0]!);\n if (p.type === \"required_parameter\" || p.type === \"optional_parameter\") {\n const pattern = p.childForFieldName(\"pattern\");\n return pattern ? tsPatternShape(pattern) : null;\n }\n return tsPatternShape(p);\n}\n\nfunction tsPatternShape(pattern: Node): string | null {\n if (pattern.type === \"identifier\") return pattern.text;\n if (pattern.type === \"rest_pattern\") return `...${pattern.namedChildren[0]?.text ?? \"\"}`;\n if (pattern.type === \"assignment_pattern\") {\n const left = pattern.childForFieldName(\"left\");\n return left ? tsPatternShape(left) : null;\n }\n return null;\n}\n\nfunction argumentShapes(call: Node): string[] | null {\n const list = call.childForFieldName(\"arguments\");\n if (!list || (list.type !== \"argument_list\" && list.type !== \"arguments\")) return null;\n const shapes: string[] = [];\n for (const a of list.namedChildren) {\n if (!a || a.type === \"comment\") continue;\n const shape = argumentShape(a);\n if (shape === null) return null;\n shapes.push(shape);\n }\n return shapes;\n}\n\nfunction argumentShape(a: Node): string | null {\n if (a.type === \"identifier\") return a.text;\n const inner = a.namedChildren[0];\n if (inner?.type !== \"identifier\") return null;\n if (a.type === \"list_splat\") return `*${inner.text}`;\n if (a.type === \"dictionary_splat\") return `**${inner.text}`;\n if (a.type === \"spread_element\") return `...${inner.text}`;\n return null;\n}\n","import type { Node } from \"web-tree-sitter\";\nimport { commentLineStats, type CommentLineStats } from \"./analysis/comment-lines.js\";\nimport { countNarratingComments } from \"./analysis/narrating-comments.js\";\nimport { isPassThrough } from \"./analysis/pass-through.js\";\nimport { symbolId } from \"./extractors/ids.js\";\nimport type { GraphMetric } from \"./types.js\";\n\n/** Comment and shape counts of one function (TP-322); `passThrough` is 1 or 0. */\nexport interface FunctionShapeStats extends CommentLineStats {\n narratingComments: number;\n passThrough: number;\n}\n\nexport interface FunctionStats extends FunctionShapeStats {\n /** Scope-qualified declared name (`Job.run`), or null for an anonymous function (e.g. `export default () => {}`). */\n name: string | null;\n cyclomatic: number;\n cognitive: number;\n nestingDepth: number;\n /** Deepest chain of rendered JSX elements in the body; 0 when it renders none. */\n jsxDepth: number;\n /** Lines spanned by the whole function node, signature included. */\n loc: number;\n}\n\ntype NumericStat = \"cyclomatic\" | \"cognitive\" | \"nestingDepth\" | \"jsxDepth\" | \"loc\" | keyof FunctionShapeStats;\n\n/** Per-symbol metric name, the unit and function stat it reports, and whether a zero is left unwritten. */\nconst SYMBOL_METRICS: readonly { name: string; stat: NumericStat; unit: string; omitZero?: boolean }[] = [\n { name: \"symbol_cognitive\", stat: \"cognitive\", unit: \"count\" },\n { name: \"symbol_cyclomatic\", stat: \"cyclomatic\", unit: \"count\" },\n { name: \"symbol_loc\", stat: \"loc\", unit: \"lines\" },\n { name: \"symbol_max_nesting\", stat: \"nestingDepth\", unit: \"count\" },\n { name: \"symbol_jsx_depth\", stat: \"jsxDepth\", unit: \"count\", omitZero: true },\n { name: \"symbol_comment_lines\", stat: \"commentLines\", unit: \"lines\" },\n { name: \"symbol_docstring_lines\", stat: \"docstringLines\", unit: \"lines\" },\n { name: \"symbol_body_lines\", stat: \"bodyLines\", unit: \"lines\" },\n { name: \"symbol_comment_ratio\", stat: \"commentRatio\", unit: \"ratio\" },\n { name: \"symbol_narrating_comments\", stat: \"narratingComments\", unit: \"count\" },\n { name: \"symbol_pass_through\", stat: \"passThrough\", unit: \"count\" },\n];\n\nexport const SYMBOL_METRIC_NAMES: readonly string[] = SYMBOL_METRICS.map((m) => m.name);\n\n/**\n * Per-symbol metrics (C-58, C-64, TP-317): for each named function whose qualified\n * name has a `symbol` node on this file, emit every SYMBOL_METRICS entry on that\n * node (`<fileId>#<qualifiedName>`), skipping an `omitZero` entry whose value is 0. Model B (C-64) gives non-exported helpers a\n * node too, so internal functions get their own values here, not just exports. A\n * qualified name shared by several functions (a getter/setter pair) takes the max\n * of each stat independently; a declared name with no function (a bare class) emits nothing.\n */\nexport function symbolMetrics(\n fileId: string,\n stats: readonly FunctionStats[],\n symbolNames: ReadonlySet<string>,\n): GraphMetric[] {\n if (symbolNames.size === 0) return [];\n const byName = new Map<string, Record<NumericStat, number>>();\n for (const s of stats) {\n if (!s.name || !symbolNames.has(s.name)) continue;\n const prev = byName.get(s.name);\n if (!prev) {\n byName.set(s.name, { ...s });\n continue;\n }\n for (const { stat } of SYMBOL_METRICS) prev[stat] = Math.max(prev[stat], s[stat]);\n }\n const out: GraphMetric[] = [];\n for (const [name, values] of byName) {\n const nodeId = symbolId(fileId, name);\n for (const m of SYMBOL_METRICS) {\n if (m.omitZero && values[m.stat] === 0) continue;\n out.push({ nodeId, name: m.name, value: values[m.stat], unit: m.unit });\n }\n }\n return out;\n}\n\n/** `fn` is the function node, `body` its body, `lines` the file's content split on newlines. */\nexport function functionShapeStats(fn: Node, body: Node, lines: readonly string[]): FunctionShapeStats {\n return {\n ...commentLineStats(fn, body, lines),\n narratingComments: countNarratingComments(fn, body),\n passThrough: isPassThrough(fn, body) ? 1 : 0,\n };\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport { EXCEPTION_METRIC_NAMES, exceptionMetrics } from \"./analysis/exception-handling.js\";\nimport { jsxDepthOf } from \"./analysis/jsx-metrics.js\";\nimport { cognitiveComplexityOf } from \"./cognitive-complexity.js\";\nimport { computeLcomMetrics } from \"./lcom.js\";\nimport { qualify, TS_BOUND_FUNCTION_TYPES, TS_FUNCTION_DECL_TYPES, walkScopes } from \"./scope-path.js\";\nimport { functionShapeStats, SYMBOL_METRIC_NAMES, symbolMetrics, type FunctionStats } from \"./symbol-metrics.js\";\nimport type { GraphMetric } from \"./types.js\";\n\nconst PY_FUNCTION_TYPES = new Set([\"function_definition\"]);\n\nconst TS_NESTING_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_statement\",\n \"try_statement\",\n]);\n\nconst PY_NESTING_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"while_statement\",\n \"try_statement\",\n]);\n\nconst TS_BRANCH_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_case\",\n \"catch_clause\",\n \"ternary_expression\",\n]);\n\nconst PY_BRANCH_TYPES = new Set([\n \"if_statement\",\n \"elif_clause\",\n \"for_statement\",\n \"while_statement\",\n \"except_clause\",\n \"conditional_expression\",\n]);\n\n/**\n * Names of every metric `computeSourceMetrics` can emit. These are pure\n * functions of a file's content, so the incremental indexer can carry them\n * forward unchanged for a byte-identical file instead of re-parsing it. If a\n * new source metric is added above, add its name here — the incremental\n * round-trip test will fail loudly if this set drifts out of sync.\n */\nexport const SOURCE_METRIC_NAMES: ReadonlySet<string> = new Set([\n \"loc\",\n \"function_count\",\n \"cyclomatic_max\",\n \"cyclomatic_sum\",\n \"cognitive_max\",\n \"cognitive_sum\",\n \"max_nesting_depth\",\n \"jsx_depth_max\",\n \"class_count\",\n \"lcom4_max\",\n ...EXCEPTION_METRIC_NAMES,\n // Per-symbol complexity, size, comments and shape (C-58, C-64, TP-317, TP-322), keyed\n // to `symbol` node ids. Source-local like the file-level metrics above, so an\n // unchanged file carries them forward — but their nodeId is `<fileId>#<name>`,\n // so the reuse basis buckets them under the symbol's parent file (incremental.ts).\n ...SYMBOL_METRIC_NAMES,\n]);\n\nconst EMPTY_NAMES: ReadonlySet<string> = new Set();\n\n/**\n * Per-file source metrics. `symbolNamesByFile` maps a file id to the names of\n * the `symbol` nodes it declares; when supplied, per-function complexity is\n * emitted on those symbol nodes (C-58; all declared functions since C-64). It\n * defaults to empty, so existing callers/tests that don't thread the symbol\n * layer keep emitting only file-level metrics.\n */\nexport function computeSourceMetrics(\n files: readonly ParsedFile[],\n fileIdOf: (filePath: string) => string,\n symbolNamesByFile: ReadonlyMap<string, ReadonlySet<string>> = new Map(),\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n for (const file of files) {\n const id = fileIdOf(file.filePath);\n out.push(...metricsForFile(id, file, symbolNamesByFile.get(id) ?? EMPTY_NAMES));\n }\n return out;\n}\n\nfunction metricsForFile(\n nodeId: string,\n file: ParsedFile,\n symbolNames: ReadonlySet<string>,\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n const loc = countLoc(file.content);\n out.push({ nodeId, name: \"loc\", value: loc, unit: \"lines\" });\n\n const stats = analyzeFunctions(file);\n out.push({\n nodeId,\n name: \"function_count\",\n value: stats.length,\n unit: \"count\",\n });\n\n if (stats.length > 0) {\n out.push({\n nodeId,\n name: \"cyclomatic_max\",\n value: Math.max(...stats.map((s) => s.cyclomatic)),\n unit: \"count\",\n });\n out.push({\n nodeId,\n name: \"cyclomatic_sum\",\n value: stats.reduce((acc, s) => acc + s.cyclomatic, 0),\n unit: \"count\",\n });\n out.push({\n nodeId,\n name: \"cognitive_max\",\n value: Math.max(...stats.map((s) => s.cognitive)),\n unit: \"count\",\n });\n out.push({\n nodeId,\n name: \"cognitive_sum\",\n value: stats.reduce((acc, s) => acc + s.cognitive, 0),\n unit: \"count\",\n });\n out.push({\n nodeId,\n name: \"max_nesting_depth\",\n value: Math.max(...stats.map((s) => s.nestingDepth)),\n unit: \"count\",\n });\n }\n const jsxDepthMax = Math.max(jsxDepthIn(file, file.tree.rootNode), ...stats.map((s) => s.jsxDepth));\n if (jsxDepthMax > 0) out.push({ nodeId, name: \"jsx_depth_max\", value: jsxDepthMax, unit: \"count\" });\n out.push(...symbolMetrics(nodeId, stats, symbolNames));\n out.push(...computeLcomMetrics(file, nodeId));\n out.push(...exceptionMetrics(nodeId, file.tree.rootNode, loc));\n return out;\n}\n\nfunction countLoc(content: string): number {\n return content.split(\"\\n\").filter((l) => l.trim() !== \"\").length;\n}\n\nfunction analyzeFunctions(file: ParsedFile): FunctionStats[] {\n const stats: FunctionStats[] = [];\n const fnTypes =\n file.language === \"python\" ? PY_FUNCTION_TYPES : TS_FUNCTION_DECL_TYPES;\n const lines = file.content.split(\"\\n\");\n walkScopes(file.tree.rootNode, file.language === \"python\", (node, scope) => {\n const fn = functionAt(node, fnTypes);\n if (!fn) return;\n stats.push({\n name: fn.name === null ? null : qualify(scope, fn.name),\n cyclomatic: cyclomaticOf(fn.body, file.language),\n cognitive: cognitiveComplexityOf(fn.body, file.language),\n nestingDepth: nestingDepthOf(fn.body, file.language, 0),\n jsxDepth: jsxDepthIn(file, fn.body),\n loc: fn.node.endPosition.row - fn.node.startPosition.row + 1,\n ...functionShapeStats(fn.node, fn.body, lines),\n });\n });\n return stats;\n}\n\n/**\n * A named, standalone function at this node, with its body and declared name —\n * or null. Covers declarations/methods (name on the node) and, crucially,\n * arrow, function or generator expression bound to a `const`/`let` (`export const foo =\n * () => {}`), where the name lives on the enclosing variable_declarator. Those\n * bindings were previously invisible to the analyzer (C-58) — a real complexity\n * under-count in an arrow-heavy codebase. Anonymous inline callbacks (parent is\n * a call, not a declarator) are intentionally excluded: their control flow\n * already rolls into the enclosing function's cognitive score.\n */\nfunction functionAt(\n node: Node,\n fnTypes: ReadonlySet<string>,\n): { name: string | null; body: Node; node: Node } | null {\n if (fnTypes.has(node.type)) {\n const body = node.childForFieldName(\"body\");\n return body ? { name: node.childForFieldName(\"name\")?.text ?? null, body, node } : null;\n }\n if (TS_BOUND_FUNCTION_TYPES.has(node.type) && node.parent?.type === \"variable_declarator\") {\n const body = node.childForFieldName(\"body\");\n if (!body) return null;\n return { name: node.parent.childForFieldName(\"name\")?.text ?? null, body, node };\n }\n return null;\n}\n\n/** JSX depth under `root`, stopping at each nested function `analyzeFunctions` scores on its own. Python has no JSX. */\nfunction jsxDepthIn(file: ParsedFile, root: Node): number {\n if (file.language === \"python\") return 0;\n return jsxDepthOf(root, (node) => functionAt(node, TS_FUNCTION_DECL_TYPES) !== null);\n}\n\nfunction nestingDepthOf(node: Node, language: string, depth: number): number {\n const nestingTypes =\n language === \"python\" ? PY_NESTING_TYPES : TS_NESTING_TYPES;\n let maxDepth = depth;\n for (const child of node.namedChildren) {\n if (!child) continue;\n const next = nestingTypes.has(child.type) ? depth + 1 : depth;\n const childMax = nestingDepthOf(child, language, next);\n if (childMax > maxDepth) maxDepth = childMax;\n }\n return maxDepth;\n}\n\nfunction cyclomaticOf(body: Node, language: string): number {\n const branchTypes =\n language === \"python\" ? PY_BRANCH_TYPES : TS_BRANCH_TYPES;\n let complexity = 1;\n const visit = (node: Node): void => {\n if (branchTypes.has(node.type)) complexity++;\n if (node.type === \"binary_expression\") {\n const op = node.childForFieldName(\"operator\");\n if (op && (op.text === \"&&\" || op.text === \"||\")) complexity++;\n }\n if (language === \"python\" && node.type === \"boolean_operator\") {\n complexity++;\n }\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(body);\n return complexity;\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/**\n * Python counterparts of the TypeScript dead-code counts in dead-code.ts (TP-318).\n * Same three counts, same bias: claim only the decidable case and never flag\n * when unsure. Where Python's semantics differ from TypeScript's, the rule is\n * noted on the function that implements it.\n */\n\nconst TERMINALS = new Set([\n \"return_statement\",\n \"raise_statement\",\n \"break_statement\",\n \"continue_statement\",\n]);\n\n/** Nodes that open a new scope: their bindings are not the enclosing function's. */\nconst SCOPE_TYPES = new Set([\"function_definition\", \"lambda\", \"class_definition\"]);\n\n/** Parameters with a splat can't be dropped from the call shape, so they stop the trailing run. */\nconst SPLAT_TYPES = new Set([\"list_splat_pattern\", \"dictionary_splat_pattern\"]);\n\nconst RECEIVERS = new Set([\"self\", \"cls\"]);\n\nexport interface DeadCodeCounts {\n unreachable: number;\n locals: number;\n params: number;\n}\n\nexport function pythonDeadCode(root: Node): DeadCodeCounts {\n const out: DeadCodeCounts = { unreachable: 0, locals: 0, params: 0 };\n const visit = (node: Node): void => {\n if (node.type === \"block\") out.unreachable += unreachableInBlock(node);\n if (node.type === \"function_definition\") {\n const r = analyzeFunction(node);\n out.locals += r.locals;\n out.params += r.params;\n }\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(root);\n return out;\n}\n\n/** Unlike TypeScript, a `def` after a terminal is not hoisted, so it counts as unreachable too. */\nfunction unreachableInBlock(block: Node): number {\n let seenTerminal = false;\n let count = 0;\n for (const child of block.namedChildren) {\n if (!child) continue;\n if (seenTerminal && child.type !== \"comment\") count++;\n if (TERMINALS.has(child.type)) seenTerminal = true;\n }\n return count;\n}\n\n/**\n * Unused locals and trailing unused parameters of one function. A name counts\n * as used when any identifier in the function's subtree (closures included)\n * reads it. A name also bound in a nested scope is skipped, as TypeScript skips\n * shadowed names; unlike TypeScript, rebinding a name in the function's own\n * scope is one local, because Python assignment does not declare.\n */\nfunction analyzeFunction(fn: Node): { locals: number; params: number } {\n const own = ownBindings(fn);\n const nested = nestedBindings(fn);\n const refs = countReferences(fn, own.declIds);\n const isUnused = (name: string): boolean =>\n !name.startsWith(\"_\") &&\n !nested.has(name) &&\n !own.declared.has(name) &&\n (refs.get(name) ?? 0) === 0;\n\n let params = 0;\n const paramNames = ownParamNames(fn);\n for (let i = isStub(fn) ? -1 : paramNames.length - 1; i >= 0; i--) {\n const name = paramNames[i] ?? null;\n if (name !== null && isUnused(name)) params++;\n else break;\n }\n const paramSet = new Set(paramNames);\n let locals = 0;\n for (const name of own.locals) {\n if (!paramSet.has(name) && isUnused(name)) locals++;\n }\n return { locals, params };\n}\n\n/** A body of only docstrings, `...`, `pass` or `raise NotImplementedError`: an `@overload` or abstract signature, like a bodiless TypeScript overload. */\nfunction isStub(fn: Node): boolean {\n const body = fn.childForFieldName(\"body\");\n return (body?.namedChildren ?? []).every((stmt) => {\n if (!stmt || stmt.type === \"comment\" || stmt.type === \"pass_statement\") return true;\n if (stmt.type === \"raise_statement\") return /^raise NotImplementedError\\b/.test(stmt.text);\n const expr = stmt.type === \"expression_statement\" ? stmt.namedChild(0) : null;\n return expr?.type === \"ellipsis\" || expr?.type === \"string\";\n });\n}\n\n/**\n * Ordered parameter names; `null` marks a position never flagged that also stops\n * the trailing run (`*args`, `**kwargs`, `self`, `cls`). `*` and `/` separators are not parameters.\n */\nfunction ownParamNames(fn: Node): (string | null)[] {\n const params = fn.childForFieldName(\"parameters\");\n if (!params) return [];\n const out: (string | null)[] = [];\n for (const p of params.namedChildren) {\n if (!p || p.type === \"keyword_separator\" || p.type === \"positional_separator\") continue;\n const id = paramIdentifier(p);\n out.push(id && !RECEIVERS.has(id.text) ? id.text : null);\n }\n return out;\n}\n\nfunction paramIdentifier(p: Node): Node | null {\n if (p.type === \"identifier\") return p;\n if (SPLAT_TYPES.has(p.type)) return null;\n const inner = p.childForFieldName(\"name\") ?? p.namedChild(0);\n return inner?.type === \"identifier\" ? inner : null;\n}\n\n/** The plain identifier an `assignment` binds, or null for unpacking, attribute, subscript or a bare annotation. */\nfunction assignedIdentifier(node: Node): Node | null {\n if (node.type !== \"assignment\" || !node.childForFieldName(\"right\")) return null;\n const left = node.childForFieldName(\"left\");\n return left?.type === \"identifier\" ? left : null;\n}\n\ninterface OwnBindings {\n /** Plain-identifier assignment targets in the function's own scope; unpacking is always-used, as TS destructuring. */\n locals: Set<string>;\n /** Names declared `global` or `nonlocal`: they are not this function's locals. */\n declared: Set<string>;\n declIds: Set<number>;\n}\n\nfunction ownBindings(fn: Node): OwnBindings {\n const out: OwnBindings = { locals: new Set(), declared: new Set(), declIds: new Set() };\n for (const p of fn.childForFieldName(\"parameters\")?.namedChildren ?? []) {\n const id = p ? paramIdentifier(p) : null;\n if (id) out.declIds.add(id.id);\n }\n const walk = (node: Node): void => {\n if (SCOPE_TYPES.has(node.type)) return;\n const id = assignedIdentifier(node);\n if (id) {\n out.locals.add(id.text);\n out.declIds.add(id.id);\n }\n if (node.type === \"global_statement\" || node.type === \"nonlocal_statement\") {\n for (const n of node.namedChildren) if (n) out.declared.add(n.text);\n }\n for (const child of node.namedChildren) if (child) walk(child);\n };\n const body = fn.childForFieldName(\"body\");\n if (body) walk(body);\n return out;\n}\n\n/** Names bound by parameters or plain assignment inside any scope nested in the function. */\nfunction nestedBindings(fn: Node): Set<string> {\n const out = new Set<string>();\n const walk = (node: Node, nested: boolean): void => {\n const inner = nested || (node !== fn && SCOPE_TYPES.has(node.type));\n if (inner) {\n const id = assignedIdentifier(node);\n if (id) out.add(id.text);\n if (node.type === \"parameters\" || node.type === \"lambda_parameters\") {\n for (const p of node.namedChildren) {\n const pid = p ? paramIdentifier(p) : null;\n if (pid) out.add(pid.text);\n }\n }\n }\n for (const child of node.namedChildren) if (child) walk(child, inner);\n };\n walk(fn, false);\n return out;\n}\n\n/** Identifier occurrences by name across the function's subtree, minus the own binding sites. */\nfunction countReferences(fn: Node, declIds: ReadonlySet<number>): Map<string, number> {\n const out = new Map<string, number>();\n const walk = (node: Node): void => {\n if (node.type === \"identifier\" && !declIds.has(node.id)) {\n out.set(node.text, (out.get(node.text) ?? 0) + 1);\n }\n for (const child of node.namedChildren) if (child) walk(child);\n };\n const body = fn.childForFieldName(\"body\");\n if (body) walk(body);\n return out;\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport type { GraphMetric } from \"../types.js\";\nimport { pythonDeadCode, type DeadCodeCounts } from \"./dead-code-python.js\";\n\n/**\n * Function-local dead-code metrics (C-65 Phase 1). Pure functions of one file's\n * bytes — the same class as the source metrics in source-metrics.ts — so they\n * ride the content-hash incremental reuse gate. Kept in their own module (not\n * appended to source-metrics.ts) so the already-churn-hot source-metrics.ts is\n * not touched; the reuse machinery folds these names in alongside\n * SOURCE_METRIC_NAMES (see incremental.ts) and index-metrics.ts computes them\n * fresh for (re)parsed files.\n */\nexport const DEAD_CODE_METRIC_NAMES: ReadonlySet<string> = new Set([\n \"unreachable_statements\",\n \"unused_locals\",\n \"unused_params\",\n]);\n\nconst FUNCTION_TYPES = new Set([\n \"function_declaration\",\n \"function_expression\",\n \"arrow_function\",\n \"method_definition\",\n \"generator_function_declaration\",\n \"generator_function\",\n]);\n\nconst PARAM_TYPES = new Set([\"required_parameter\", \"optional_parameter\"]);\n\n/** Statements that unconditionally end control flow in their block. */\nconst TERMINALS = new Set([\n \"return_statement\",\n \"throw_statement\",\n \"break_statement\",\n \"continue_statement\",\n]);\n\n/**\n * Per-file dead-code metrics for TypeScript and Python files (Python since\n * TP-318, in dead-code-python.ts). Emitted sparsely — only when a count is > 0 —\n * so a clean file adds no rows (a full index and an incremental re-index\n * therefore produce the identical metric set). Other languages are skipped.\n */\nexport function computeDeadCodeMetrics(\n files: readonly ParsedFile[],\n fileIdOf: (filePath: string) => string,\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n for (const file of files) {\n const counts = deadCodeOf(file);\n if (!counts) continue;\n const id = fileIdOf(file.filePath);\n const { unreachable, locals, params } = counts;\n if (unreachable > 0) {\n out.push({ nodeId: id, name: \"unreachable_statements\", value: unreachable, unit: \"count\" });\n }\n if (locals > 0) {\n out.push({ nodeId: id, name: \"unused_locals\", value: locals, unit: \"count\" });\n }\n if (params > 0) {\n out.push({ nodeId: id, name: \"unused_params\", value: params, unit: \"count\" });\n }\n }\n return out;\n}\n\nfunction deadCodeOf(file: ParsedFile): DeadCodeCounts | null {\n const root = file.tree.rootNode;\n if (file.language === \"python\") return pythonDeadCode(root);\n if (file.language !== \"typescript\" && file.language !== \"tsx\") return null;\n return { unreachable: countUnreachable(root), ...countUnusedBindings(root) };\n}\n\n/**\n * Count statements that can never execute: those following an unconditional\n * terminal (`return`/`throw`/`break`/`continue`) inside the SAME\n * `statement_block`. Deliberately shallow — no CFG — so it only claims the\n * decidable case and stays near-zero false-positive:\n * - `switch` bodies are not plain blocks (fallthrough / `case` labels), so their\n * statements are never in a `statement_block` here and aren't counted.\n * - Anything after a conditional (an `if` with no guaranteed terminal) is not\n * counted, because the terminal must be a direct child of the block.\n * - A `function_declaration` after a terminal is hoisted (callable before the\n * terminal), so it is excluded; comments are ignored too.\n */\nfunction countUnreachable(root: Node): number {\n let count = 0;\n const visit = (node: Node): void => {\n if (node.type === \"statement_block\") count += unreachableInBlock(node);\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(root);\n return count;\n}\n\nfunction unreachableInBlock(block: Node): number {\n let seenTerminal = false;\n let count = 0;\n for (const child of block.namedChildren) {\n if (!child) continue;\n if (\n seenTerminal &&\n child.type !== \"comment\" &&\n child.type !== \"function_declaration\"\n ) {\n count++;\n }\n if (TERMINALS.has(child.type)) seenTerminal = true;\n }\n return count;\n}\n\n/**\n * Count unused *local variables* and *parameters* across every function in the\n * file, function-locally and conservatively (bias to NOT flag — false positives\n * are worse than misses for a health signal). Each function is analysed\n * independently; a binding is \"unused\" when its name is never referenced within\n * the function's subtree (nested closures included).\n *\n * Only PLAIN-identifier bindings are considered — destructuring/rest/pattern\n * params and locals are treated as always-used and never flagged (their\n * omit-some-keys usage is usually deliberate, and reasoning about them soundly\n * needs a scope tree). Further cuts: `_`-prefixed names (intentional-ignore) are\n * skipped; a name declared more than once anywhere in the function (shadowing) is\n * skipped rather than risk a wrong count; and an unused parameter is only counted\n * when every parameter after it is also unused (TS6133's rule — you can't drop a\n * middle parameter, only a trailing run).\n */\nfunction countUnusedBindings(root: Node): { locals: number; params: number } {\n let locals = 0;\n let params = 0;\n const visit = (node: Node): void => {\n if (FUNCTION_TYPES.has(node.type)) {\n const r = analyzeFunction(node);\n locals += r.locals;\n params += r.params;\n }\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(root);\n return { locals, params };\n}\n\nfunction analyzeFunction(fn: Node): { locals: number; params: number } {\n // All plain-id binding declarations in the subtree (own + nested): their nodes\n // are excluded from reference counts, and a name seen twice marks a shadow.\n const declIds = new Set<number>();\n const nameCount = new Map<string, number>();\n collectBindingDecls(fn, declIds, nameCount);\n\n const refs = new Map<string, number>();\n countReferences(fn, declIds, refs);\n\n const isUnused = (name: string): boolean =>\n !name.startsWith(\"_\") &&\n (nameCount.get(name) ?? 0) <= 1 &&\n (refs.get(name) ?? 0) === 0;\n\n // Params: only the trailing run of unused params counts (TS6133 middle-param rule).\n const paramNames = ownParamNames(fn);\n let params = 0;\n for (let i = paramNames.length - 1; i >= 0; i--) {\n const name = paramNames[i] ?? null;\n if (name !== null && isUnused(name)) params++;\n else break;\n }\n\n let locals = 0;\n for (const name of ownLocalNames(fn)) {\n if (isUnused(name)) locals++;\n }\n return { locals, params };\n}\n\n/**\n * Ordered parameter names of a function's `formal_parameters`. A non-plain\n * parameter (destructuring/rest) yields `null` — a position we never flag and\n * which stops the trailing-unused run (you can't drop params after it).\n * Bare single-identifier arrow params (`x => …`, no parens) are not analysed.\n */\nfunction ownParamNames(fn: Node): (string | null)[] {\n const params = fn.childForFieldName(\"parameters\");\n if (!params) return [];\n const out: (string | null)[] = [];\n for (const p of params.namedChildren) {\n if (!p || !PARAM_TYPES.has(p.type)) continue;\n const first = p.namedChild(0);\n out.push(first?.type === \"identifier\" ? first.text : null);\n }\n return out;\n}\n\n/**\n * Names of plain-identifier locals declared in the function's OWN scope — walking\n * the body but not descending into nested functions (those bindings belong to the\n * nested function). Destructuring declarators are skipped.\n */\nfunction ownLocalNames(fn: Node): string[] {\n const body = fn.childForFieldName(\"body\");\n if (!body) return [];\n const out: string[] = [];\n const walk = (node: Node): void => {\n if (FUNCTION_TYPES.has(node.type)) return;\n if (node.type === \"variable_declarator\") {\n const name = node.childForFieldName(\"name\");\n if (name?.type === \"identifier\") out.push(name.text);\n }\n for (const child of node.namedChildren) {\n if (child) walk(child);\n }\n };\n walk(body);\n return out;\n}\n\n/** Record every plain-id binding declaration node (param/local, own + nested). */\nfunction collectBindingDecls(\n fn: Node,\n ids: Set<number>,\n nameCount: Map<string, number>,\n): void {\n const mark = (n: Node | null): void => {\n if (n?.type !== \"identifier\") return;\n ids.add(n.id);\n nameCount.set(n.text, (nameCount.get(n.text) ?? 0) + 1);\n };\n const walk = (node: Node): void => {\n if (PARAM_TYPES.has(node.type)) mark(node.namedChild(0));\n else if (node.type === \"variable_declarator\") mark(node.childForFieldName(\"name\"));\n for (const child of node.namedChildren) {\n if (child) walk(child);\n }\n };\n walk(fn);\n}\n\n/** Count value references (identifier / object-shorthand) by name, minus declarations. */\nfunction countReferences(\n fn: Node,\n declIds: ReadonlySet<number>,\n out: Map<string, number>,\n): void {\n const walk = (node: Node): void => {\n if (\n (node.type === \"identifier\" ||\n node.type === \"shorthand_property_identifier\") &&\n !declIds.has(node.id)\n ) {\n out.set(node.text, (out.get(node.text) ?? 0) + 1);\n }\n for (const child of node.namedChildren) {\n if (child) walk(child);\n }\n };\n walk(fn);\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport type { Node } from \"web-tree-sitter\";\nimport type { GraphMetric } from \"../types.js\";\n\n/**\n * Growth-risk / scaling-smell metrics (C-66 Phase 2). Cheap, function-local\n * *heuristics* — NOT Big-O or a proven complexity class (real asymptotic\n * inference is undecidable; see the roadmap's hard NO). Pure functions of one\n * file's bytes, so they ride the content-hash incremental reuse gate, folded\n * into the carry-forward set in incremental.ts alongside the source/dead-code\n * metric names. Emitted sparsely (only when a smell is present).\n */\nexport const GROWTH_RISK_METRIC_NAMES: ReadonlySet<string> = new Set([\n \"loop_depth\",\n \"recursive_functions\",\n \"search_in_loop\",\n]);\n\nconst TS_LOOP_TYPES = new Set([\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n]);\n\nconst PY_LOOP_TYPES = new Set([\"for_statement\", \"while_statement\"]);\n\nconst NAMED_FN_TYPES = new Set([\n \"function_declaration\",\n \"generator_function_declaration\",\n \"method_definition\",\n \"function_definition\",\n]);\n\n/**\n * Array/collection methods that scan linearly — inside a loop they turn an O(n)\n * pass into an O(n·m) one (a scaling smell). `.includes`/`.indexOf` on a `Set`\n * or `Map` are O(1), so this is a heuristic, not a bound.\n */\nconst SEARCH_METHODS = new Set([\n \"includes\",\n \"indexOf\",\n \"lastIndexOf\",\n \"find\",\n \"findIndex\",\n \"some\",\n \"every\",\n \"filter\",\n]);\n\n/**\n * Per-file growth-risk metrics for TS/Python files, all SMELLS not bounds:\n * - `loop_depth` — max *lexical* loop nesting (triple-nested → 3), emitted at\n * depth ≥ 2 (depth-2 loops over two *different* collections are actually linear).\n * - `recursive_functions` — named functions that call themselves directly.\n * - `search_in_loop` — linear-scan method calls (`.includes`/`.find`/…) inside a\n * loop (an O(n) scan per iteration; `.includes` on a `Set` is O(1)).\n * All emitted sparsely (only when present). Non-TS/Python files are skipped.\n */\nexport function computeGrowthRiskMetrics(\n files: readonly ParsedFile[],\n fileIdOf: (filePath: string) => string,\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n for (const file of files) {\n const loopTypes = file.language === \"python\" ? PY_LOOP_TYPES : TS_LOOP_TYPES;\n const root = file.tree.rootNode;\n const id = fileIdOf(file.filePath);\n const depth = maxLoopDepth(root, loopTypes, 0);\n if (depth >= 2) {\n out.push({ nodeId: id, name: \"loop_depth\", value: depth, unit: \"count\" });\n }\n const recursion = countDirectRecursion(root);\n if (recursion > 0) {\n out.push({ nodeId: id, name: \"recursive_functions\", value: recursion, unit: \"count\" });\n }\n const searches = countSearchInLoop(root, loopTypes, false);\n if (searches > 0) {\n out.push({ nodeId: id, name: \"search_in_loop\", value: searches, unit: \"count\" });\n }\n }\n return out;\n}\n\n/**\n * Count named functions that call themselves directly by name — a recursion flag\n * (unbounded recursion is a scaling risk). Function-local and conservative: only\n * a plain `name(...)` call inside the same function counts; method self-calls\n * via `this.m()` and mutual recursion (which would need a call graph — a roadmap\n * hard NO) are out of scope. A name shadowed by a nested same-named function is\n * not distinguished (rare).\n */\nfunction countDirectRecursion(root: Node): number {\n let count = 0;\n const visit = (node: Node): void => {\n if (NAMED_FN_TYPES.has(node.type)) {\n const name = node.childForFieldName(\"name\")?.text;\n const body = node.childForFieldName(\"body\");\n if (name && body && callsName(body, name)) count++;\n }\n for (const child of node.namedChildren) {\n if (child) visit(child);\n }\n };\n visit(root);\n return count;\n}\n\n/** Whether `node`'s subtree contains a direct call `name(...)`. */\nfunction callsName(node: Node, name: string): boolean {\n if (node.type === \"call_expression\") {\n const fn = node.childForFieldName(\"function\");\n if (fn?.type === \"identifier\" && fn.text === name) return true;\n }\n for (const child of node.namedChildren) {\n if (child && callsName(child, name)) return true;\n }\n return false;\n}\n\n/**\n * Count linear-scan method calls (`.includes`/`.find`/…) that occur inside a\n * loop — an O(n) search per iteration, a quadratic-shaped smell. `inLoop`\n * tracks whether the current node is lexically inside a loop body.\n */\nfunction countSearchInLoop(\n node: Node,\n loopTypes: ReadonlySet<string>,\n inLoop: boolean,\n): number {\n let count = 0;\n if (inLoop && node.type === \"call_expression\") {\n const fn = node.childForFieldName(\"function\");\n const prop = fn?.type === \"member_expression\" ? fn.childForFieldName(\"property\") : null;\n if (prop && SEARCH_METHODS.has(prop.text)) count++;\n }\n const childInLoop = inLoop || loopTypes.has(node.type);\n for (const child of node.namedChildren) {\n if (child) count += countSearchInLoop(child, loopTypes, childInLoop);\n }\n return count;\n}\n\n/** Deepest lexical nesting of loop constructs under `node`. */\nfunction maxLoopDepth(\n node: Node,\n loopTypes: ReadonlySet<string>,\n depth: number,\n): number {\n let max = depth;\n for (const child of node.namedChildren) {\n if (!child) continue;\n const next = loopTypes.has(child.type) ? depth + 1 : depth;\n const childMax = maxLoopDepth(child, loopTypes, next);\n if (childMax > max) max = childMax;\n }\n return max;\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport { buildFileModuleNodes } from \"./extractors/file-nodes.js\";\nimport { collectDeclaredSpans, type LineSpan } from \"./declared-names.js\";\nimport type { ReuseBasis } from \"./incremental.js\";\nimport type { GraphFragment, GraphNode } from \"./types.js\";\n\n/**\n * Rebuild an unchanged file's graph fragment from the prior snapshot. Produces\n * byte-for-byte the same nodes and edges the extractor would emit: file +\n * module nodes (path-derived), the symbol nodes it declares (content-derived,\n * so carried forward from the basis rather than rebuilt — C-53), the external\n * nodes its imports reference, and the outbound edges carried forward verbatim.\n */\nexport function reconstructFragment(\n repoRoot: string,\n absPath: string,\n fileId: string,\n basis: ReuseBasis,\n): GraphFragment {\n const nodes = buildFileModuleNodes(repoRoot, absPath);\n nodes.push(...(basis.symbolsByFile.get(fileId) ?? []));\n const edges = basis.edgesBySrc.get(fileId) ?? [];\n const seenExternals = new Set<string>();\n for (const edge of edges) {\n const dst = basis.nodesById.get(edge.dstId);\n if (dst?.kind === \"external\" && !seenExternals.has(dst.id)) {\n seenExternals.add(dst.id);\n nodes.push({ id: dst.id, kind: \"external\", name: dst.name });\n }\n }\n return { nodes, edges };\n}\n\n/**\n * Reconstruct a COSMETIC file's fragment (C-18): its edges + file/module/external\n * nodes are structure-invariant so they come from the basis verbatim, but its\n * symbol line spans shifted with the moved comments/whitespace, so those are\n * refreshed from the fresh parse. Produces byte-for-byte what a full extract\n * would — same names, same `exported`, same edges — with up-to-date spans, while\n * skipping the ts-morph extract entirely. Its loc + AST metrics are recomputed\n * from the same parse by the normal metrics path.\n */\nexport function reconstructCosmetic(\n repoRoot: string,\n absPath: string,\n fileId: string,\n basis: ReuseBasis,\n parsed: ParsedFile,\n): GraphFragment {\n const base = reconstructFragment(repoRoot, absPath, fileId, basis);\n const spans = collectDeclaredSpans(parsed);\n const nodes = base.nodes.map((n) =>\n n.kind === \"symbol\" ? withRefreshedSpan(n, spans) : n,\n );\n return { nodes, edges: base.edges };\n}\n\n/**\n * A symbol node with its line span refreshed from a fresh parse. Span-less\n * symbols (exported types/consts, which never carry startLine) are returned\n * unchanged; a function/method/class symbol takes the freshly-parsed span for\n * its name, matching exactly what the extractor would emit.\n */\nfunction withRefreshedSpan(\n node: GraphNode,\n spans: ReadonlyMap<string, LineSpan>,\n): GraphNode {\n const attrs = node.attrs as\n | { exported?: boolean; startLine?: number; endLine?: number }\n | undefined;\n if (!attrs || attrs.startLine === undefined) return node;\n const span = spans.get(node.name);\n if (!span) return node;\n return {\n ...node,\n attrs: { ...attrs, startLine: span.startLine, endLine: span.endLine },\n };\n}\n","import { RESOLVABLE_EXTS } from \"./extractors/module-resolution.js\";\nimport { parseSymbolId } from \"./extractors/ids.js\";\nimport type { ReuseBasis } from \"./incremental.js\";\nimport type { GraphEdge } from \"./types.js\";\n\n/**\n * Partial reuse across a file-membership delta (C-20). PR #28 fell back to a full\n * index whenever any file was added or removed, because a byte-identical file's\n * import edges resolve against the *global* file set and can change when a\n * referenced path appears or disappears. This narrows that: only files whose\n * edges are actually affected by the delta re-extract; every other unchanged\n * file is still reused.\n *\n * A stored edge carries its original `specifier`, so an unchanged file's relative\n * imports can be re-resolved over the new file-id set — no filesystem, no\n * ts-morph — to detect two effects: a target that was removed, and a target now\n * shadowed by an added file at a higher-priority resolution path.\n *\n * Known limitation (documented, sound-for-valid-code): a previously *unresolved*\n * relative import (which left no edge — a broken import in a file that didn't\n * compile) that an added file now satisfies is not detected, because there is no\n * stored specifier to re-resolve. Such a file is reused until it next changes.\n */\n\n/** Posix dirname of a repo-relative file id (`a/b/c.ts` → `a/b`). */\nfunction dirOf(id: string): string {\n const i = id.lastIndexOf(\"/\");\n return i < 0 ? \"\" : id.slice(0, i);\n}\n\n/** Normalize a posix path, collapsing `.` and `..` segments. */\nfunction normalizePosix(p: string): string {\n const out: string[] = [];\n for (const seg of p.split(\"/\")) {\n if (seg === \"\" || seg === \".\") continue;\n if (seg === \"..\") out.pop();\n else out.push(seg);\n }\n return out.join(\"/\");\n}\n\nconst JS_EXT_RE = /\\.(?:jsx?|mjs|cjs)$/;\n\n/** Candidate file ids a relative import base could resolve to, in priority order\n * — mirrors the extractor's `relativeResolutionCandidates` in id space. */\nfunction* candidateIds(base: string): Iterable<string> {\n yield base;\n for (const ext of RESOLVABLE_EXTS) yield base + ext;\n const jsExt = JS_EXT_RE.exec(base);\n if (jsExt) {\n const stem = base.slice(0, base.length - jsExt[0].length);\n for (const ext of RESOLVABLE_EXTS) yield stem + ext;\n }\n for (const ext of RESOLVABLE_EXTS) yield `${base}/index${ext}`;\n}\n\nfunction isRelative(specifier: string): boolean {\n return specifier === \".\" || specifier === \"..\" ||\n specifier.startsWith(\"./\") || specifier.startsWith(\"../\");\n}\n\n/**\n * Resolve a relative specifier from a source file id to a target file id in the\n * current file set, or null when nothing matches — the id-space equivalent of the\n * extractor's filesystem walk, so it yields the same target for the same inputs.\n */\nexport function resolveRelativeId(\n srcFileId: string,\n specifier: string,\n fileIds: ReadonlySet<string>,\n): string | null {\n const base = normalizePosix(`${dirOf(srcFileId)}/${specifier}`);\n for (const candidate of candidateIds(base)) {\n if (fileIds.has(candidate)) return candidate;\n }\n return null;\n}\n\n/** The file id an edge's target belongs to (a symbol target `f#x` → `f`). */\nfunction targetFileId(edge: GraphEdge): string {\n return parseSymbolId(edge.dstId)?.fileId ?? edge.dstId;\n}\n\n/**\n * File ids that must re-extract because the membership delta changed how their\n * imports resolve: an edge target was removed, or a relative specifier now\n * resolves to a different file (e.g. an added file shadowing the old target).\n * Empty when membership is unchanged — the caller then reuses exactly as before.\n */\nexport function computeDeltaAffected(\n basis: ReuseBasis,\n currentFileIds: ReadonlySet<string>,\n): Set<string> {\n const affected = new Set<string>();\n const removed = new Set<string>();\n for (const id of basis.fingerprints.keys()) {\n if (!currentFileIds.has(id)) removed.add(id);\n }\n const added = currentFileIds.size !== basis.fingerprints.size || removed.size > 0;\n if (!added) return affected; // membership unchanged → nothing forced\n\n for (const [srcId, edges] of basis.edgesBySrc) {\n if (!currentFileIds.has(srcId)) continue; // src itself gone\n for (const edge of edges) {\n if (isEdgeAffected(edge, srcId, removed, currentFileIds)) {\n affected.add(srcId);\n break;\n }\n }\n }\n return affected;\n}\n\nfunction isEdgeAffected(\n edge: GraphEdge,\n srcId: string,\n removed: ReadonlySet<string>,\n currentFileIds: ReadonlySet<string>,\n): boolean {\n if (removed.has(targetFileId(edge))) return true;\n const specifier = (edge.attrs as { specifier?: string } | undefined)?.specifier;\n if (!specifier || !isRelative(specifier)) return false;\n // Re-resolve the relative import; if it now lands on a different file (added\n // shadow, or the old target vanished), the file's edges must be recomputed.\n return resolveRelativeId(srcId, specifier, currentFileIds) !== targetFileId(edge);\n}\n","import type { GraphEdge, GraphMetric, GraphNode } from \"./types.js\";\nimport { edgeWeight, resolveBarrelEdges } from \"./barrel-resolve.js\";\n\ninterface DegreeCounts {\n fanIn: Map<string, number>;\n fanOut: Map<string, number>;\n}\n\n/**\n * fan_in / fan_out are file/module *structural* coupling — how many modules a\n * file depends on, and vice versa. They count only `imports`/`re-exports`\n * edges; the per-symbol `references` layer (C-53) is a finer granularity and\n * must not inflate module degree (one references edge per imported *symbol*\n * would turn \"depends on 3 modules\" into \"names 30 symbols\").\n */\nfunction isStructuralEdge(e: GraphEdge): boolean {\n return e.kind === \"imports\" || e.kind === \"re-exports\";\n}\n\nfunction countDegrees(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n): DegreeCounts {\n const fanIn = new Map<string, number>();\n const fanOut = new Map<string, number>();\n for (const n of nodes) {\n fanIn.set(n.id, 0);\n fanOut.set(n.id, 0);\n }\n for (const e of edges) {\n if (!isStructuralEdge(e)) continue;\n if (fanOut.has(e.srcId)) {\n fanOut.set(e.srcId, fanOut.get(e.srcId)! + 1);\n }\n if (fanIn.has(e.dstId)) {\n fanIn.set(e.dstId, fanIn.get(e.dstId)! + 1);\n }\n }\n return { fanIn, fanOut };\n}\n\n/**\n * Utilization: inbound edges weighted by their reference count (C-51's\n * `attrs.weight`), so it measures how heavily a file's exports are actually\n * *used*, not merely how many files name it. Computed over the\n * BARREL-RESOLVED edge set (C-53), so re-export plumbing is credited to the\n * files that do the work rather than to the `index.ts` hub everything routes\n * through. A pure barrel therefore reads utilization ~0 (fan_in still counts\n * its raw importers) — a clean re-export-hub signature. Deterministic over the\n * assembled edge set, so it stays correct under incremental reuse.\n */\nfunction weightedInbound(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n): Map<string, number> {\n const util = new Map<string, number>();\n for (const n of nodes) util.set(n.id, 0);\n for (const e of resolveBarrelEdges(nodes, edges)) {\n if (e.kind === \"calls\") continue;\n if (util.has(e.dstId)) util.set(e.dstId, util.get(e.dstId)! + edgeWeight(e));\n }\n return util;\n}\n\nexport function computeMetrics(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n): GraphMetric[] {\n const { fanIn, fanOut } = countDegrees(nodes, edges);\n const utilization = weightedInbound(nodes, edges);\n const out: GraphMetric[] = [];\n for (const n of nodes) {\n // Symbol nodes carry only utilization (how heavily the export is used).\n // fan_in/fan_out/instability are module-structural and don't apply — and\n // skipping them keeps the per-export layer from tripling the metric table.\n if (n.kind === \"symbol\") {\n out.push({ nodeId: n.id, name: \"utilization\", value: utilization.get(n.id) ?? 0, unit: \"count\" });\n continue;\n }\n const ci = fanIn.get(n.id) ?? 0;\n const co = fanOut.get(n.id) ?? 0;\n out.push({ nodeId: n.id, name: \"fan_in\", value: ci, unit: \"count\" });\n out.push({ nodeId: n.id, name: \"fan_out\", value: co, unit: \"count\" });\n out.push({ nodeId: n.id, name: \"utilization\", value: utilization.get(n.id) ?? 0, unit: \"count\" });\n if (ci + co > 0) {\n out.push({\n nodeId: n.id,\n name: \"instability\",\n value: co / (ci + co),\n unit: \"ratio\",\n });\n }\n }\n return out;\n}\n","import { readParamShape, type CallEdgeAttrs, type CallSite, type ParamShape } from \"../extractors/call-sites.js\";\nimport { parseSymbolId } from \"../extractors/ids.js\";\nimport type { GraphEdge, GraphMetric, GraphNode } from \"../types.js\";\n\nexport const CALL_METRIC_NAMES: ReadonlySet<string> = new Set([\n \"symbol_caller_count\",\n \"symbol_single_caller_helper\",\n \"symbol_constant_params\",\n]);\n\n/** Placeholder for a parameter a site does not pass; no literal's source text can equal it. */\nconst ABSENT = \"<absent>\";\n\ninterface Inbound {\n callers: Set<string>;\n sites: CallSite[];\n}\n\n/**\n * Call-graph metrics over the assembled `calls` edges (TP-323). They depend on\n * edges from every file, so they are recomputed on each index rather than\n * carried forward with a reused file. Written on each function, method and\n * class symbol (the nodes with a line span): `symbol_caller_count`, the distinct\n * other symbols or files that call it; `symbol_single_caller_helper`, 1 for a\n * non-exported, non-dunder symbol whose one caller is a symbol; and, once a callable has 2\n * resolved call sites, `symbol_constant_params`.\n */\nexport function computeCallMetrics(nodes: Iterable<GraphNode>, edges: Iterable<GraphEdge>): GraphMetric[] {\n const inbound = collectInbound(edges);\n const out: GraphMetric[] = [];\n for (const node of nodes) {\n if (node.kind !== \"symbol\" || node.attrs?.startLine === undefined) continue;\n const { callers, sites } = inbound.get(node.id) ?? { callers: new Set<string>(), sites: [] };\n out.push({ nodeId: node.id, name: \"symbol_caller_count\", value: callers.size, unit: \"count\" });\n const single = isPrivateHelper(node) && callers.size === 1 && isSymbolCaller(callers);\n out.push({ nodeId: node.id, name: \"symbol_single_caller_helper\", value: single ? 1 : 0, unit: \"count\" });\n const shape = readParamShape(node.attrs);\n if (shape && sites.length >= 2) {\n out.push({ nodeId: node.id, name: \"symbol_constant_params\", value: constantParams(shape, sites), unit: \"count\" });\n }\n }\n return out;\n}\n\n/** Callers exclude the callee itself, so recursion is not a caller; its sites still count. */\nfunction collectInbound(edges: Iterable<GraphEdge>): Map<string, Inbound> {\n const inbound = new Map<string, Inbound>();\n for (const edge of edges) {\n if (edge.kind !== \"calls\") continue;\n let entry = inbound.get(edge.dstId);\n if (!entry) inbound.set(edge.dstId, (entry = { callers: new Set(), sites: [] }));\n if (edge.srcId !== edge.dstId) entry.callers.add(edge.srcId);\n entry.sites.push(...((edge.attrs as CallEdgeAttrs | undefined)?.sites ?? []));\n }\n return inbound;\n}\n\n/** Non-exported, and not a Python `__dunder__`, which the runtime calls through its protocol. */\nfunction isPrivateHelper(node: GraphNode): boolean {\n const own = node.name.slice(node.name.lastIndexOf(\".\") + 1);\n return node.attrs?.exported === false && !(own.startsWith(\"__\") && own.endsWith(\"__\"));\n}\n\nfunction isSymbolCaller(callers: ReadonlySet<string>): boolean {\n return [...callers].every((id) => parseSymbolId(id) !== null);\n}\n\n/** Parameters every site passes the same literal, or none passes; unknown at any site means not constant. */\nexport function constantParams(shape: ParamShape, sites: readonly CallSite[]): number {\n let count = 0;\n shape.params.forEach((name, index) => {\n const values = sites.map((site) => argumentAt(site, name, index < shape.positional ? index : -1));\n if (values.every((v) => v !== null && v === values[0])) count++;\n });\n return count;\n}\n\n/** The literal text a site passes for one parameter, ABSENT when it passes nothing, or null when unknown. */\nfunction argumentAt(site: CallSite, name: string, position: number): string | null {\n if (position >= 0 && position < site.args.length) return site.args[position] ?? null;\n if (site.kwargs && Object.hasOwn(site.kwargs, name)) return site.kwargs[name] ?? null;\n if (site.kwSplat) return null;\n if (position >= 0 && site.spreadFrom !== undefined && position >= site.spreadFrom) return null;\n return ABSENT;\n}\n","import {\n aggregateChurnWindows,\n authorLinesByPath,\n computeOwnership,\n entriesWithin,\n loadChurnEntries,\n loadFileFirstSeen,\n type ChurnEntry,\n type ChurnWindow,\n type PathChurn,\n summarizeOwnership,\n} from \"./history/index.js\";\nimport { groupTestsBySource, type TestSourceLink } from \"./analysis/test-linker.js\";\nimport { computeRecencyWindows, round3, windowSuffix } from \"./history-recency.js\";\nimport type { GraphMetric, GraphNode } from \"./types.js\";\n\nexport interface HistoryMetricsOptions {\n /** Primary window: scopes ownership. Default 30. */\n churnWindowDays?: number;\n /** Windows to store churn and recency for; default {@link DEFAULT_CHURN_WINDOWS}, primary always included. */\n churnWindows?: number[];\n /** Also store an all-time `lifetime` window over full git history. */\n includeLifetime?: boolean;\n /** Epoch seconds that windows end at; defaults to the current time. */\n nowEpoch?: number;\n /** Read history up to this rev instead of HEAD; pair it with the rev's commit time as `nowEpoch`. */\n rev?: string;\n}\n\n/** Windows the dashboard switcher offers; churn is stored for each by default. */\nexport const DEFAULT_CHURN_WINDOWS = [30, 90, 180];\n\n/** De-duped, ascending windows including the primary, with `lifetime` last (widest) when requested. */\nexport function resolveChurnWindows(\n requested: number[] | undefined,\n primaryWindow: number,\n includeLifetime: boolean,\n): ChurnWindow[] {\n const base = requested && requested.length > 0 ? requested : DEFAULT_CHURN_WINDOWS;\n const finite = [...new Set([primaryWindow, ...base])].filter((w) => w > 0).sort((a, b) => a - b);\n return includeLifetime ? [...finite, \"lifetime\"] : finite;\n}\n\nexport interface LoadedHistory {\n metrics: GraphMetric[];\n /** Churn entries inside the primary window, which also scopes test-coverage linking and ownership. */\n primaryEntries: readonly ChurnEntry[];\n}\n\n/**\n * Git-history metrics for a snapshot's file nodes: churn and recency per window,\n * ownership for the primary window (and lifetime when requested). Node ids are\n * the history engine's repo-relative paths, because both are rooted at `idRoot`.\n * Returns [] when git or history is unavailable.\n */\nexport function buildHistoryMetrics(\n nodes: Iterable<GraphNode>,\n idRoot: string,\n options: HistoryMetricsOptions = {},\n): GraphMetric[] {\n return loadHistoryMetrics(nodes, idRoot, options)?.metrics ?? [];\n}\n\n/** {@link buildHistoryMetrics} plus the primary-window entries it read; null when git or history is unavailable. */\nexport function loadHistoryMetrics(\n nodes: Iterable<GraphNode>,\n idRoot: string,\n options: HistoryMetricsOptions = {},\n): LoadedHistory | null {\n const knownPaths = collectFileIds(nodes);\n const primaryWindow = options.churnWindowDays ?? 30;\n const windows = resolveChurnWindows(options.churnWindows, primaryWindow, options.includeLifetime === true);\n // Load the widest window once and slice it per window; lifetime sorts widest.\n const wide = loadChurnEntries({\n repoRoot: idRoot,\n windowDays: windows[windows.length - 1]!,\n rev: options.rev,\n untilEpoch: options.nowEpoch,\n });\n if (wide === null) return null;\n const nowEpoch = options.nowEpoch ?? Math.floor(Date.now() / 1000);\n const churnByWindow = aggregateChurnWindows(wide, windows, nowEpoch, knownPaths);\n const primaryEntries = windows.at(-1) === primaryWindow ? wide : entriesWithin(wide, primaryWindow, nowEpoch);\n const metrics = [\n ...churnMetrics(churnByWindow),\n ...ownershipMetrics(primaryEntries, primaryWindow, knownPaths),\n ...recencyMetrics({ idRoot, rev: options.rev, knownPaths, nowEpoch }, churnByWindow),\n ];\n // Lifetime ownership is the dominant owner over full history; `wide` is full history when lifetime is on.\n if (options.includeLifetime === true) metrics.push(...ownershipMetrics(wide, \"lifetime\", knownPaths));\n return { metrics, primaryEntries };\n}\n\nexport function collectFileIds(nodes: Iterable<GraphNode>): Set<string> {\n const out = new Set<string>();\n for (const n of nodes) {\n if (n.kind === \"file\") out.add(n.id);\n }\n return out;\n}\n\n/** Name one window's per-path churn as `churn_{w}`, `churn_{w}_commits`, `churn_{w}_authors`. */\nexport function churnMetrics(churnByWindow: ReadonlyMap<ChurnWindow, ReadonlyMap<string, PathChurn>>): GraphMetric[] {\n const out: GraphMetric[] = [];\n for (const [window, byPath] of churnByWindow) {\n const suffix = windowSuffix(window);\n for (const [nodeId, churn] of byPath) {\n out.push(\n { nodeId, name: `churn_${suffix}`, value: churn.lines, unit: \"lines\" },\n { nodeId, name: `churn_${suffix}_commits`, value: churn.commits, unit: \"count\" },\n { nodeId, name: `churn_${suffix}_authors`, value: churn.authors, unit: \"count\" },\n );\n }\n }\n return out;\n}\n\n/** Name ownership as `bus_factor_{w}` and `top_author_share_{w}` (rounded to 3 places). */\nexport function ownershipMetrics(\n entries: readonly ChurnEntry[],\n window: ChurnWindow,\n knownPaths?: ReadonlySet<string>,\n): GraphMetric[] {\n const suffix = windowSuffix(window);\n const out: GraphMetric[] = [];\n for (const [nodeId, owner] of computeOwnership(entries, { knownPaths })) {\n out.push(\n { nodeId, name: `bus_factor_${suffix}`, value: owner.busFactor, unit: \"count\" },\n { nodeId, name: `top_author_share_${suffix}`, value: round3(owner.topAuthorShare), unit: \"ratio\" },\n );\n }\n return out;\n}\n\nexport interface TestCoverageOwnershipOptions {\n /** Window named in the metric suffix. Default 30. */\n windowDays?: ChurnWindow;\n /** Coverage threshold for bus factor (default 0.5 = 50% of churn). */\n busFactorThreshold?: number;\n}\n\n/**\n * Bus-factor / top-author-share of the *test coverage* for each source, keyed\n * on the source node. Aggregates churn authorship across all test files linked\n * to a source (via the two-pass linker) and summarises it the same way as\n * production ownership — so a file can read as well-spread on production code\n * yet a single-author silo on its tests (or vice versa). Emitted only for\n * sources with at least one linked test that has churn in the window.\n */\nexport function computeTestCoverageOwnership(\n entries: readonly ChurnEntry[],\n links: readonly TestSourceLink[],\n options: TestCoverageOwnershipOptions = {},\n): GraphMetric[] {\n const suffix = windowSuffix(options.windowDays ?? 30);\n const testsBySource = groupTestsBySource(links);\n const testIds = new Set<string>();\n for (const tests of testsBySource.values()) {\n for (const t of tests) testIds.add(t);\n }\n const linesByTest = authorLinesByPath(entries, testIds);\n const out: GraphMetric[] = [];\n for (const [nodeId, tests] of testsBySource) {\n const summary = summarizeOwnership(mergeAuthorChurn(tests, linesByTest), options.busFactorThreshold);\n if (summary === null) continue;\n out.push(\n { nodeId, name: `test_bus_factor_${suffix}`, value: summary.busFactor, unit: \"count\" },\n { nodeId, name: `test_top_author_share_${suffix}`, value: round3(summary.topAuthorShare), unit: \"ratio\" },\n );\n }\n return out;\n}\n\n/** Sum per-author churn across a set of test files into one author tally. */\nfunction mergeAuthorChurn(\n tests: ReadonlySet<string>,\n linesByTest: ReadonlyMap<string, Map<string, number>>,\n): Map<string, number> {\n const byAuthor = new Map<string, number>();\n for (const testId of tests) {\n const fileAuthors = linesByTest.get(testId);\n if (!fileAuthors) continue;\n for (const [author, lines] of fileAuthors) {\n byAuthor.set(author, (byAuthor.get(author) ?? 0) + lines);\n }\n }\n return byAuthor;\n}\n\n/** Recency for files that churned in each window; an unknown first-seen date still yields recency 1. */\nfunction recencyMetrics(\n at: { idRoot: string; rev: string | undefined; knownPaths: ReadonlySet<string>; nowEpoch: number },\n churnByWindow: ReadonlyMap<ChurnWindow, ReadonlyMap<string, PathChurn>>,\n): GraphMetric[] {\n const churnedByWindow = new Map<ChurnWindow, ReadonlySet<string>>();\n for (const [window, byPath] of churnByWindow) {\n if (byPath.size > 0) churnedByWindow.set(window, new Set(byPath.keys()));\n }\n if (churnedByWindow.size === 0) return [];\n const firstSeen =\n loadFileFirstSeen({ repoRoot: at.idRoot, knownPaths: at.knownPaths, rev: at.rev }) ?? new Map<string, number>();\n return computeRecencyWindows(firstSeen, churnedByWindow, at.nowEpoch);\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport { computeMetrics } from \"./metrics.js\";\nimport { computeSourceMetrics } from \"./source-metrics.js\";\nimport { computeDeadCodeMetrics } from \"./analysis/dead-code.js\";\nimport { computeCallMetrics } from \"./analysis/call-metrics.js\";\nimport { computeGrowthRiskMetrics } from \"./analysis/growth-risk.js\";\nimport { fileId } from \"./extractors/ids.js\";\nimport { linkTestsToSources, testCoverageCountMetrics } from \"./analysis/test-linker.js\";\nimport { computeChangeCoupling, type ChurnEntry } from \"./history/index.js\";\nimport {\n collectFileIds,\n computeTestCoverageOwnership,\n loadHistoryMetrics,\n type HistoryMetricsOptions,\n} from \"./history-metrics.js\";\nimport type { GraphEdge, GraphMetric, GraphNode } from \"./types.js\";\n\nexport interface IndexerMetricsInput {\n nodes: Map<string, GraphNode>;\n edges: Map<string, GraphEdge>;\n /** Files (re)parsed this run — source metrics are computed fresh for these. */\n parsedFiles: ParsedFile[];\n /** Source metrics carried forward verbatim for reused (unchanged) files. */\n reusedSourceMetrics: GraphMetric[];\n idRoot: string;\n /** Git-history metrics (churn, recency, ownership); omitted means none. */\n history?: HistoryMetricsOptions;\n}\n\n/**\n * Map each file id to the names of the `symbol` nodes it declares, so\n * `computeSourceMetrics` can attach per-function complexity. Reflects the\n * assembled node set (parsed + reused symbol nodes alike), so per-symbol\n * complexity is emitted for exactly the names that have a symbol node.\n */\nfunction symbolNamesByFile(nodes: Iterable<GraphNode>): Map<string, Set<string>> {\n const out = new Map<string, Set<string>>();\n for (const n of nodes) {\n if (n.kind !== \"symbol\" || !n.parentId) continue;\n const bucket = out.get(n.parentId);\n if (bucket) bucket.add(n.name);\n else out.set(n.parentId, new Set([n.name]));\n }\n return out;\n}\n\n/**\n * Assemble the metric set for a snapshot: graph-wide degree metrics over the\n * full node/edge set, freshly-computed source metrics for (re)parsed files, and\n * reused source metrics carried forward for unchanged files. Everything but the\n * reused source metrics is recomputed over the full set, so the result matches a\n * full index regardless of how much was reused.\n *\n * Git-history metrics come from the path-based engine in `./history/` through\n * the `history-metrics.ts` adapter. Test-coverage metrics run with or without it.\n */\nexport function buildIndexerMetrics(input: IndexerMetricsInput): GraphMetric[] {\n const nodeList = [...input.nodes.values()];\n const history = input.history ? loadHistoryMetrics(nodeList, input.idRoot, input.history) : null;\n return [\n ...computeMetrics(nodeList, [...input.edges.values()]),\n ...computeCallMetrics(nodeList, input.edges.values()),\n ...computeSourceMetrics(\n input.parsedFiles,\n (p) => fileId(input.idRoot, p),\n symbolNamesByFile(nodeList),\n ),\n ...computeDeadCodeMetrics(input.parsedFiles, (p) => fileId(input.idRoot, p)),\n ...computeGrowthRiskMetrics(input.parsedFiles, (p) => fileId(input.idRoot, p)),\n ...input.reusedSourceMetrics,\n ...(history?.metrics ?? []),\n ...computeTestCoverage(nodeList, history?.primaryEntries ?? null, input.history?.churnWindowDays),\n ];\n}\n\n/**\n * Two-pass test↔source linker outputs: per-source coverage counts (always) and,\n * when churn is available, the bus-factor / top-author-share of each source's\n * test coverage. Path-convention links need no churn; co-edit supplementation\n * and the ownership split reuse the already-loaded churn entries.\n */\nfunction computeTestCoverage(\n nodes: readonly GraphNode[],\n entries: readonly ChurnEntry[] | null,\n windowDays: number | undefined,\n): GraphMetric[] {\n const coEditPairs = entries ? computeChangeCoupling(entries, { knownPaths: collectFileIds(nodes) }).pairs : [];\n const links = linkTestsToSources(nodes, coEditPairs);\n if (links.length === 0) return [];\n const out = testCoverageCountMetrics(links);\n if (entries) {\n out.push(...computeTestCoverageOwnership(entries, links, { windowDays }));\n }\n return out;\n}\n","import type { GraphEdge, GraphFragment, GraphNode } from \"./types.js\";\n\nexport interface ExtractAccumulator {\n nodes: Map<string, GraphNode>;\n edges: Map<string, GraphEdge>;\n}\n\n/**\n * JSON-encoded so ids containing the separator can't collide (paths may hold\n * spaces). Mirrors the `(snapshot_id, src_id, dst_id, kind)` edge primary key.\n */\nfunction edgeKey(edge: GraphEdge): string {\n return JSON.stringify([edge.srcId, edge.dstId, edge.kind]);\n}\n\n/** First fragment wins per id, so walk order decides shared nodes exactly as a full index would. */\nexport function mergeFragments(fragments: readonly GraphFragment[]): ExtractAccumulator {\n const nodes = new Map<string, GraphNode>();\n const edges = new Map<string, GraphEdge>();\n for (const fragment of fragments) {\n for (const node of fragment.nodes) if (!nodes.has(node.id)) nodes.set(node.id, node);\n for (const edge of fragment.edges) {\n const key = edgeKey(edge);\n if (!edges.has(key)) edges.set(key, edge);\n }\n }\n return { nodes, edges };\n}\n","import type { ParsedFile } from \"@titan-design/code-parser\";\nimport { collectDeclarations } from \"./declared-names.js\";\nimport { symbolId } from \"./extractors/ids.js\";\nimport type { IdAlias } from \"./types.js\";\n\n/** The first index version whose symbol ids carry the enclosing scopes (`f.ts#Job.run`, TP-182). */\nexport const QUALIFIED_SYMBOLS_SINCE = \"0.14.0\";\n\nfunction versionParts(version: string): number[] | null {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(version);\n return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;\n}\n\n/** True when a snapshot's index version wrote bare-name symbol ids; an unversioned snapshot counts as older. */\nexport function predatesQualifiedSymbols(indexVersion: string): boolean {\n const have = versionParts(indexVersion);\n if (!have) return true;\n const since = versionParts(QUALIFIED_SYMBOLS_SINCE)!;\n for (let i = 0; i < 3; i++) {\n if (have[i] !== since[i]) return have[i]! < since[i]!;\n }\n return false;\n}\n\n/**\n * Aliases from the bare-name symbol ids older index versions wrote (`f.ts#run`)\n * to the qualified ids that replaced them (`f.ts#Job.run`). Written only where\n * the mapping is unambiguous: exactly one qualified name in the file descends\n * from the bare name, and the bare id is not itself still a node. Where two\n * classes both define `run`, the old node merged them and no alias is recorded.\n */\nexport function qualifiedSymbolAliases(\n files: Iterable<{ fileId: string; file: ParsedFile }>,\n nodeIds: ReadonlySet<string>,\n): IdAlias[] {\n const out: IdAlias[] = [];\n for (const { fileId, file } of files) {\n for (const [name, qualified] of qualifiedByName(file)) {\n const oldId = symbolId(fileId, name);\n if (qualified.size !== 1 || nodeIds.has(oldId)) continue;\n const newId = symbolId(fileId, [...qualified][0]!);\n if (nodeIds.has(newId)) out.push({ oldId, newId, reason: \"requalify\" });\n }\n }\n return out;\n}\n\nfunction qualifiedByName(file: ParsedFile): Map<string, Set<string>> {\n const out = new Map<string, Set<string>>();\n for (const d of collectDeclarations(file)) {\n const bucket = out.get(d.name);\n if (bucket) bucket.add(d.qualifiedName);\n else out.set(d.name, new Set([d.qualifiedName]));\n }\n return out;\n}\n","export type {\n EdgeKind,\n FileFingerprint,\n GraphEdge,\n GraphFragment,\n GraphMetric,\n GraphNode,\n IdAlias,\n IdAliasReason,\n NodeKind,\n NodeRole,\n SnapshotRow,\n} from \"./types.js\";\n\nexport type { SnapshotInsert } from \"./store.js\";\nexport { CodeGraphStore, openCodeGraph } from \"./store.js\";\nexport { DOMAIN_DDL, FINDING_DDL, KIT, MIGRATIONS, SCHEMA_VERSION, SNAPSHOT_SCOPED_TABLES } from \"./schema.js\";\nexport type { PruneOptions, PrunePlan, PruneResult } from \"./prune.js\";\nexport { planPrune, runPrune } from \"./prune.js\";\n\nexport type { IndexOptions, IndexResult } from \"./indexer.js\";\nexport { INDEX_VERSION, indexPaths } from \"./indexer.js\";\nexport type { IndexSource } from \"./index-source.js\";\nexport { workingTreeSource } from \"./index-source.js\";\nexport { gitTreeSource } from \"./git-tree-source.js\";\n\nexport type { Extractor, ParsedFile } from \"@titan-design/code-parser\";\nexport { getLanguageFromPath, getSupportedLanguages, parseFile, shouldIncludeFile } from \"@titan-design/code-parser\";\n\nexport type { LanguageExtractorOptions } from \"./extractors/dispatch.js\";\nexport { LanguageExtractor } from \"./extractors/dispatch.js\";\nexport { PythonGraphExtractor } from \"./extractors/python-extractor.js\";\nexport type { TsMorphGraphExtractorOptions } from \"./extractors/ts-morph-extractor.js\";\nexport { TsMorphGraphExtractor } from \"./extractors/ts-morph-extractor.js\";\nexport { buildFileModuleNodes } from \"./extractors/file-nodes.js\";\nexport type { DeepAst, DeepAstInput, MemberInfo, ParamInfo } from \"./extractors/deep-ast.js\";\nexport { computeDeepAst } from \"./extractors/deep-ast.js\";\nexport {\n externalId,\n fileId,\n moduleId,\n packageId,\n parentModuleId,\n parseSymbolId,\n symbolId,\n SYMBOL_ID_SEP,\n} from \"./extractors/ids.js\";\n\nexport type { ReadFile, ReuseBasis, SourceLanguage } from \"./incremental.js\";\nexport { hashContent, readSourceFiles, structuralSignature } from \"./incremental.js\";\nexport { walkSourceFiles } from \"./file-walk.js\";\nexport { collectDeclaredNames, collectDeclaredSpans, type LineSpan } from \"./declared-names.js\";\nexport { edgeWeight, pruneDanglingReferences, resolveBarrelEdges } from \"./barrel-resolve.js\";\nexport { ALL_ROLES, annotateRoles, classifyRole, computeRoleHints, loadRoleGlobs } from \"./roles.js\";\nexport { UNIMPORTED_ROLES } from \"./unimported-roles.js\";\nexport type { AnnotateRolesOptions, RoleHints } from \"./roles.js\";\nexport type { RoleGlobs } from \"./role-globs.js\";\nexport { isGeneratedByHeuristic, isGeneratedFile, loadGeneratedPatterns } from \"./generated.js\";\nexport { canonicalEdgeKind, canonicalMetricName, canonicalRole } from \"./aliases.js\";\nexport {\n buildAliases,\n detectGitHead,\n detectGitToplevel,\n detectRenames,\n isInsideGitRepo,\n resolveGitRef,\n} from \"./git-renames.js\";\nexport type { AliasChain, AliasChainInput, AliasLoader, AliasResolution } from \"./identity/alias-chain.js\";\nexport { createAliasChain } from \"./identity/alias-chain.js\";\nexport type { Lineage, LineageSnapshot, LineageStep } from \"./identity/lineage.js\";\nexport { ALIAS_BASE_ATTR, buildLineage, lineagePath } from \"./identity/lineage.js\";\nexport type { AliasChainOptions, PriorSnapshotOptions, ResolveAliasOptions } from \"./identity/store-identity.js\";\nexport { aliasChain, loadLineage, priorSnapshotForRef, resolveAlias } from \"./identity/store-identity.js\";\nexport { computeMetrics } from \"./metrics.js\";\nexport { computeSourceMetrics, SOURCE_METRIC_NAMES } from \"./source-metrics.js\";\nexport { SYMBOL_METRIC_NAMES } from \"./symbol-metrics.js\";\nexport { EXCEPTION_METRIC_NAMES } from \"./analysis/exception-handling.js\";\nexport { buildIndexerMetrics } from \"./index-metrics.js\";\nexport { computeDeadCodeMetrics, DEAD_CODE_METRIC_NAMES } from \"./analysis/dead-code.js\";\nexport { computeGrowthRiskMetrics, GROWTH_RISK_METRIC_NAMES } from \"./analysis/growth-risk.js\";\nexport type { LinkMethod, LinkTestsOptions, TestSourceLink } from \"./analysis/test-linker.js\";\nexport { groupTestsBySource, linkTestsToSources, testCoverageCountMetrics } from \"./analysis/test-linker.js\";\nexport type { IstanbulCoverage, SymbolSpan } from \"./analysis/coverage.js\";\nexport { attributeCoverage, COVERAGE_METRIC_NAME } from \"./analysis/coverage.js\";\nexport type { MinifiedSource, MinifyLanguage } from \"./analysis/context/minify.js\";\nexport { importMarker, isMinifyLanguage, minifySource, originalLine } from \"./analysis/context/minify.js\";\n/**\n * The history adapter: it turns `./history`'s primitives into `GraphMetric` rows, so it\n * lives at the root rather than behind the `./history` seam, which speaks no graph types.\n */\nexport type { HistoryMetricsOptions, LoadedHistory, TestCoverageOwnershipOptions } from \"./history-metrics.js\";\nexport {\n computeTestCoverageOwnership,\n DEFAULT_CHURN_WINDOWS,\n loadHistoryMetrics,\n resolveChurnWindows,\n} from \"./history-metrics.js\";\nexport { computeRecencyWindows, windowSuffix } from \"./history-recency.js\";\nexport type { PageRankOptions, PageRankResult, PageRankRow } from \"./analysis/pagerank.js\";\nexport { computePageRank, getEdgeWeight } from \"./analysis/pagerank.js\";\nexport type { RelevanceOptions } from \"./analysis/relevance.js\";\nexport { computeRelevance } from \"./analysis/relevance.js\";\nexport {\n DEFAULT_MAX_LINE_CHARS,\n ELISION_MARKER,\n TRUNCATION_SUFFIX,\n renderSignatureTree,\n} from \"./analysis/context/signature-tree.js\";\nexport type { SignatureTreeOptions } from \"./analysis/context/signature-tree.js\";\nexport type {\n Consumers,\n ContextBuildInput,\n ContextDossier,\n FileDossier,\n FileOwnership,\n Provenance,\n SymbolDossier,\n SymbolLine,\n} from \"./analysis/context/dossier.js\";\nexport { buildContextDossier, SCHEMA_VERSION as CONTEXT_SCHEMA_VERSION } from \"./analysis/context/dossier.js\";\nexport { renderContextMarkdown } from \"./analysis/context/format.js\";\nexport type {\n BundleBuildInput,\n BundleEdge,\n BundleEdges,\n ContextBundle,\n Coverage,\n SourceChunk,\n} from \"./analysis/context/bundle.js\";\nexport { BUNDLE_SCHEMA_VERSION, buildContextBundle, renderBundleText } from \"./analysis/context/bundle.js\";\nexport type {\n ReferenceEdgeLite,\n SymbolConsumers,\n SymbolCouplingOptions,\n SymbolCouplingPair,\n} from \"./analysis/symbol-coupling.js\";\nexport { computeSymbolConsumers, computeSymbolCoupling } from \"./analysis/symbol-coupling.js\";\nexport type {\n PackageFlag,\n PackageLayer,\n PackageStats,\n PairCoupling,\n PairFlag,\n PartitionQualityInput,\n PartitionQualityResult,\n} from \"./analysis/partition-quality.js\";\nexport { computePartitionQuality, invertBuckets } from \"./analysis/partition-quality.js\";\nexport {\n snapshotPageRank,\n snapshotReferenceEdges,\n snapshotRelevance,\n snapshotSymbolConsumers,\n snapshotSymbolCoupling,\n} from \"./analysis/snapshot.js\";\nexport type {\n BusFactorChange,\n BusFactorRow,\n CentralRow,\n CouplingDelta,\n CouplingRow,\n DeadModuleRow,\n GraphReportResult,\n GrowthRiskRow,\n HotspotDelta,\n HotspotRow,\n NewHotspot,\n ReportDrift,\n TestCoverageRow,\n UnusedExportRow,\n UntestedRiskRow,\n} from \"./analysis/graph-report-types.js\";\nexport type { ReportContext, ReportContextInput } from \"./analysis/graph-report-sections.js\";\nexport {\n buildReportContext,\n busFactorOf,\n hotspotScoreOf,\n keepNode,\n lookupMetric,\n topBusFactorRisks,\n topCentralFiles,\n topHotspots,\n topTestCoverageRisks,\n} from \"./analysis/graph-report-sections.js\";\nexport { publicApiFiles, topUnusedExports } from \"./analysis/unused-exports.js\";\nexport { topDeadModules } from \"./analysis/dead-modules.js\";\nexport { topGrowthRisks } from \"./analysis/growth-risks.js\";\nexport { topUntestedRisks } from \"./analysis/untested-risks.js\";\nexport type { ComputeDriftInput } from \"./analysis/graph-report-drift.js\";\nexport { computeReportDrift } from \"./analysis/graph-report-drift.js\";\nexport type { HealthComponent, HealthComponentKey, HealthInput, HealthWeights, PenaltyWeight } from \"./analysis/dashboard-health.js\";\nexport { DEFAULT_HEALTH_WEIGHTS, computeHealth } from \"./analysis/dashboard-health.js\";\nexport type {\n BlastRadiusEntry,\n HotExport,\n NodeMetrics,\n SymbolUtil,\n} from \"./analysis/dashboard-node-metrics.js\";\nexport {\n buildBlastRadius,\n buildCentralFiles,\n buildHotExports,\n buildNodeMetrics,\n collectNodeMetrics,\n collectSymbolUtil,\n referencedNodes,\n} from \"./analysis/dashboard-node-metrics.js\";\nexport type {\n SymbolConsumerGroup,\n SymbolConsumerRow,\n SymbolCouplingPayload,\n SymbolCouplingRow,\n} from \"./analysis/dashboard-symbol-coupling.js\";\nexport { buildSymbolCouplingPayload } from \"./analysis/dashboard-symbol-coupling.js\";\nexport type { CouplingClass, SnapshotContext } from \"./analysis/dashboard-coupling.js\";\nexport { classifyCoupling, pairKey } from \"./analysis/dashboard-coupling.js\";\nexport type { PackageRoot } from \"./analysis/package-buckets.js\";\nexport { bucketFilesByPackage } from \"./analysis/package-buckets.js\";\nexport type {\n ArchEdge,\n ArchPackage,\n ArchResult,\n ArchSubNode,\n} from \"./analysis/graph-arch-types.js\";\nexport type { ComputeArchInput } from \"./analysis/graph-arch-compute.js\";\nexport {\n DEFAULT_MAX_PACKAGE_SIZE,\n EXTERNAL_BUCKET,\n aggregateEdges,\n computeArch,\n filteredFileIds,\n packagesReferencedByEdges,\n toSortedEdges,\n} from \"./analysis/graph-arch-compute.js\";\n\n/** Convenience readers over one snapshot; the store carries the full query surface. */\nexport { listEdges, listMetrics, listNodes } from \"./read.js\";\nexport type { MetricAggregate, TopMetricRow } from \"./store-reads.js\";\nexport { aggregateMetrics, listEdgesTouching, listMetricsForNode } from \"./read.js\";\nexport type {\n MetricAbsence,\n MetricDescriptor,\n MetricDirection,\n MetricRollup,\n MetricSource,\n MetricUnit,\n} from \"./catalogue/types.js\";\nexport { METRIC_CATALOGUE } from \"./catalogue/entries.js\";\nexport { describeMetric, describeMetrics } from \"./catalogue/describe.js\";\n\nexport type {\n CheckResult,\n CheckRule,\n CheckRulesFile,\n CheckViolation,\n ForbidImportRule,\n LayeredDepsRule,\n MetricMaxRule,\n MetricMinRule,\n MetricOutlierRule,\n MetricProductMaxRule,\n NoInternalOnlyBarrelsRule,\n Severity,\n} from \"./check/types.js\";\nexport type { RunChecksOptions } from \"./check/check.js\";\nexport { rebasedViolationKey, runChecks, snapshotViolations, violationKey } from \"./check/check.js\";\nexport type { RuleStore } from \"./check/context.js\";\nexport type { ExternalDiagnostic, Finding } from \"./check/findings.js\";\nexport { externalToFinding, toFindings } from \"./check/findings.js\";\nexport type {\n FindingKeyInput,\n StoredFinding,\n StoredVerdict,\n VerdictCitation,\n VerdictLabel,\n} from \"./check/finding-store.js\";\nexport {\n carryForwardVerdicts,\n findingKey,\n hashText,\n keyFindings,\n listFindings,\n listVerdicts,\n normalizeFlaggedText,\n saveFindings,\n saveVerdicts,\n} from \"./check/finding-store.js\";\nexport { compilePatterns, matchesAny, patternToRegex } from \"./check/patterns.js\";\nexport type { ValidateRulesOptions } from \"./check/validate.js\";\nexport { validateRules } from \"./check/validate.js\";\nexport { DEFAULT_OUTLIER_MIN_SAMPLE, percentileOf } from \"./check/outlier-rule.js\";\nexport type { CheckSnapshotOptions, CheckSnapshotResult, SnapshotSpec } from \"./check/run.js\";\nexport { checkSnapshot, loadCheckRules, resolveSnapshot } from \"./check/run.js\";\n\nexport type { GraphDiff, GraphDiffSummary, MetricDelta, NodeRename } from \"./diff/types.js\";\nexport type { DiffSnapshotsOptions } from \"./diff/diff.js\";\nexport { diffSnapshots } from \"./diff/diff.js\";\nexport type { CheckDiff, DiffCheckResultsOptions, UnchangedViolation } from \"./diff/check-diff.js\";\nexport { diffCheckResults } from \"./diff/check-diff.js\";\nexport type { BucketableViolation, ViolationBuckets } from \"./diff/violation-buckets.js\";\nexport { bucketViolations } from \"./diff/violation-buckets.js\";\nexport type { ViolationIdentity } from \"./check/violation-key.js\";\nexport type {\n FootprintGraph,\n FootprintOptions,\n FootprintParts,\n FootprintUnit,\n SymbolFootprint,\n} from \"./diff/footprint.js\";\nexport { computeFootprints, symbolSetHash } from \"./diff/footprint.js\";\nexport type { FootprintChange, FootprintChangeReason, FootprintDiff } from \"./diff/types.js\";\nexport type { DiffFootprintsOptions } from \"./diff/footprint-diff.js\";\nexport { diffFootprints } from \"./diff/footprint-diff.js\";\nexport type {\n GateResult,\n GateUnitsInput,\n RegenerateReason,\n UnitProvenance,\n UnitProvenanceInput,\n UnitRegeneration,\n} from \"./diff/gate.js\";\nexport { gateUnits, unitProvenance } from \"./diff/gate.js\";\n\nexport type {\n EmbedAttempt,\n EmbedCoverage,\n EmbeddableSymbol,\n EmbedSnapshotResult,\n FindSimilarOptions,\n SimilarCandidate,\n SimilarResult,\n} from \"./embeddings/types.js\";\nexport { buildEmbedText, hashEmbedText, listEmbeddableSymbols } from \"./embeddings/corpus.js\";\nexport type { CachedEmbedResult } from \"./embeddings/cache.js\";\nexport { embedTextsCached, SYMBOL_EMBEDDING_NAMESPACE } from \"./embeddings/cache.js\";\nexport { embedSnapshot, findSimilarCapability, tryEmbedSnapshot } from \"./embeddings/embeddings.js\";\n\nexport type {\n ConventionArea,\n ConventionCorpus,\n ConventionCoverage,\n ConventionMap,\n ConventionMatch,\n ConventionOptions,\n ConventionQueryResult,\n ConventionSymbol,\n FindConventionsOptions,\n SummarizeConventionsResult,\n Summarizer,\n} from \"./conventions/types.js\";\nexport { detectCommunities } from \"./conventions/communities.js\";\nexport { buildConventionAreas, defaultTargetCount } from \"./conventions/areas.js\";\nexport { COMMUNITY_SUMMARY_NAMESPACE, getConventionMap, summarizeConventions } from \"./conventions/summaries.js\";\nexport { findConventions } from \"./conventions/query.js\";\n","import { readFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n Node,\n Project,\n ScriptTarget,\n type ArrowFunction,\n type ClassDeclaration,\n type FunctionDeclaration,\n type FunctionExpression,\n type InterfaceDeclaration,\n type MethodDeclaration,\n type SourceFile,\n} from \"ts-morph\";\nimport { declarationText, lookupDeclaration } from \"./symbol-signature.js\";\n\n/**\n * C-81 — **deep AST on-pull**. Structural facts too heavy to persist at index\n * time (class members, per-parameter types, return type) are recomputed lazily\n * here from the working-tree source when a consumer actually pulls a target.\n * Persisting them would bloat every symbol node and break the incremental reuse\n * basis (inferred types embed absolute `import(\"…\")` paths); computing on demand\n * keeps the index lean while still answering \"what are the members / params of\n * this\" for the one target being read.\n *\n * A single-file in-memory ts-morph project (no tsconfig, no dependency walk) —\n * so the extraction is cheap and reads only explicit syntactic annotations.\n */\nexport interface ParamInfo {\n name: string;\n type: string | null;\n}\n\nexport interface MemberInfo {\n name: string;\n memberKind: string;\n signature: string | null;\n isStatic: boolean;\n}\n\nexport interface DeepAst {\n target: string;\n kind: \"file\" | \"symbol\";\n declarationKind: string | null;\n signature: string | null;\n purpose: string | null;\n params: ParamInfo[];\n returnType: string | null;\n /** Class/interface members for a symbol; exported declarations for a file. */\n members: MemberInfo[];\n note?: string;\n}\n\nexport interface DeepAstInput {\n /** Repo-relative file id, e.g. `src/a.ts`. */\n filePath: string;\n /** Absolute path to the file on disk. */\n absPath: string;\n /** Symbol name for a symbol target; omit for a file target. */\n symbolName?: string;\n}\n\ntype Callable =\n | FunctionDeclaration\n | MethodDeclaration\n | ArrowFunction\n | FunctionExpression;\n\n/** Deep structural facts for one target, or null when the source is unreadable. */\nexport function computeDeepAst(input: DeepAstInput): DeepAst | null {\n const sf = loadSourceFile(input.absPath);\n if (!sf) return null;\n const target = input.symbolName\n ? `${input.filePath}#${input.symbolName}`\n : input.filePath;\n return input.symbolName\n ? symbolDeepAst(sf, input.symbolName, target)\n : fileDeepAst(sf, target);\n}\n\nfunction loadSourceFile(absPath: string): SourceFile | null {\n try {\n const text = readFileSync(absPath, \"utf8\");\n const project = new Project({\n useInMemoryFileSystem: true,\n compilerOptions: { target: ScriptTarget.Latest, allowJs: true },\n });\n return project.createSourceFile(`f${path.extname(absPath) || \".ts\"}`, text);\n } catch {\n return null;\n }\n}\n\nfunction symbolDeepAst(sf: SourceFile, name: string, target: string): DeepAst {\n const decl = lookupDeclaration(sf, name);\n if (!decl) {\n return { ...empty(target, \"symbol\"), note: \"declaration not found in source\" };\n }\n const text = declarationText(decl);\n return {\n target,\n kind: \"symbol\",\n declarationKind: decl.getKindName(),\n signature: text.signature ?? null,\n purpose: text.purpose ?? null,\n params: paramsOf(decl),\n returnType: returnTypeOf(decl),\n members: membersOf(decl),\n };\n}\n\nfunction fileDeepAst(sf: SourceFile, target: string): DeepAst {\n return {\n ...empty(target, \"file\"),\n declarationKind: \"SourceFile\",\n members: exportedDeclarations(sf),\n };\n}\n\nfunction empty(target: string, kind: \"file\" | \"symbol\"): DeepAst {\n return {\n target,\n kind,\n declarationKind: null,\n signature: null,\n purpose: null,\n params: [],\n returnType: null,\n members: [],\n };\n}\n\n/** Unwrap a declaration to the callable it defines, or null for non-callables. */\nfunction callableOf(decl: Node): Callable | null {\n if (Node.isFunctionDeclaration(decl) || Node.isMethodDeclaration(decl)) return decl;\n if (Node.isVariableDeclaration(decl)) {\n const init = decl.getInitializer();\n if (init && (Node.isArrowFunction(init) || Node.isFunctionExpression(init))) return init;\n }\n return null;\n}\n\nfunction paramsOf(decl: Node): ParamInfo[] {\n const callable = callableOf(decl);\n if (!callable) return [];\n return callable.getParameters().map((p) => ({\n name: p.getName(),\n type: p.getTypeNode()?.getText() ?? null,\n }));\n}\n\nfunction returnTypeOf(decl: Node): string | null {\n return callableOf(decl)?.getReturnTypeNode()?.getText() ?? null;\n}\n\nfunction membersOf(decl: Node): MemberInfo[] {\n if (Node.isClassDeclaration(decl)) return classMembers(decl);\n if (Node.isInterfaceDeclaration(decl)) return interfaceMembers(decl);\n return [];\n}\n\nfunction classMembers(cls: ClassDeclaration): MemberInfo[] {\n return cls.getMembers().map((m) => ({\n name: memberName(m),\n memberKind: m.getKindName(),\n signature: memberSignature(m),\n isStatic: Node.isStaticable(m) ? m.isStatic() : false,\n }));\n}\n\nfunction interfaceMembers(iface: InterfaceDeclaration): MemberInfo[] {\n return iface.getMembers().map((m) => ({\n name: memberName(m),\n memberKind: m.getKindName(),\n signature: memberSignature(m),\n isStatic: false,\n }));\n}\n\nfunction exportedDeclarations(sf: SourceFile): MemberInfo[] {\n const out: MemberInfo[] = [];\n for (const [name, decls] of sf.getExportedDeclarations()) {\n const decl = decls[0];\n if (!decl) continue;\n out.push({\n name,\n memberKind: decl.getKindName(),\n signature: declarationText(decl).signature ?? memberSignature(decl),\n isStatic: false,\n });\n }\n return out;\n}\n\nfunction memberName(m: Node): string {\n if (Node.isConstructorDeclaration(m)) return \"constructor\";\n return Node.hasName(m) ? m.getName() : \"\";\n}\n\nfunction memberSignature(m: Node): string | null {\n if (\n Node.isMethodDeclaration(m) ||\n Node.isMethodSignature(m) ||\n Node.isConstructorDeclaration(m)\n ) {\n const params = m.getParameters().map((p) => oneLine(p.getText())).join(\", \");\n const ret = m.getReturnTypeNode()?.getText();\n const name = Node.isConstructorDeclaration(m) ? \"constructor\" : memberName(m);\n return oneLine(`${name}(${params})${ret ? `: ${ret}` : \"\"}`);\n }\n if (Node.isPropertyDeclaration(m) || Node.isPropertySignature(m)) {\n const type = m.getTypeNode()?.getText();\n return oneLine(`${memberName(m)}${type ? `: ${type}` : \"\"}`);\n }\n return null;\n}\n\nfunction oneLine(s: string): string {\n return s.replace(/\\s+/g, \" \").trim();\n}\n","import type { EdgeKind, NodeRole } from \"./types.js\";\n\n/**\n * Schema-healing aliases: deprecated or synonymous spellings mapped to the one\n * canonical name codewatch emits today. Two jobs:\n *\n * 1. Rename tolerance on snapshot diff — a metric/edge-kind renamed between an\n * old snapshot and a new one is reconciled to its canonical name so it\n * lines up instead of surfacing as a spurious add/remove.\n * 2. Config tolerance — an external `.codewatch/check.json` that spells a\n * metric or role with a separator/plural variant loads with a deprecation\n * warning and the canonical name, not a hard error.\n *\n * Seeds are conservative: only separator (`-`/`_`), singular/plural, and\n * unambiguous synonym variants of names codewatch actually produces. Add a real\n * historical rename here when one lands; nothing maps a name to a *different*\n * concept.\n */\n\nconst METRIC_ALIASES: ReadonlyMap<string, string> = new Map([\n [\"lines\", \"loc\"],\n [\"lines_of_code\", \"loc\"],\n [\"fan-in\", \"fan_in\"],\n [\"fanin\", \"fan_in\"],\n [\"fan-out\", \"fan_out\"],\n [\"fanout\", \"fan_out\"],\n [\"nesting_depth\", \"max_nesting_depth\"],\n [\"max-nesting-depth\", \"max_nesting_depth\"],\n [\"lcom4\", \"lcom4_max\"],\n]);\n\nconst ROLE_ALIASES: ReadonlyMap<string, string> = new Map([\n [\"tests\", \"test\"],\n [\"spec\", \"test\"],\n [\"specs\", \"test\"],\n [\"fixtures\", \"fixture\"],\n [\"barrels\", \"barrel\"],\n]);\n\nconst EDGE_KIND_ALIASES: ReadonlyMap<string, string> = new Map([\n [\"import\", \"imports\"],\n [\"call\", \"calls\"],\n [\"reference\", \"references\"],\n [\"re_exports\", \"re-exports\"],\n [\"reexports\", \"re-exports\"],\n [\"re-export\", \"re-exports\"],\n [\"depends_on\", \"depends-on\"],\n [\"dependson\", \"depends-on\"],\n]);\n\n/** Canonical name for a deprecated alias, or `undefined` if `name` is not aliased. */\nexport function deprecatedTarget(\n map: ReadonlyMap<string, string>,\n name: string,\n): string | undefined {\n return map.get(name);\n}\n\nexport function canonicalMetricName(name: string): string {\n return METRIC_ALIASES.get(name) ?? name;\n}\n\nexport function canonicalRole(name: string): NodeRole {\n return (ROLE_ALIASES.get(name) ?? name) as NodeRole;\n}\n\nexport function canonicalEdgeKind(name: string): EdgeKind {\n return (EDGE_KIND_ALIASES.get(name) ?? name) as EdgeKind;\n}\n\n/** Canonical metric name for a deprecated alias, or `undefined`. */\nexport function metricAliasTarget(name: string): string | undefined {\n return deprecatedTarget(METRIC_ALIASES, name);\n}\n\n/** Canonical role for a deprecated alias, or `undefined`. */\nexport function roleAliasTarget(name: string): NodeRole | undefined {\n return deprecatedTarget(ROLE_ALIASES, name) as NodeRole | undefined;\n}\n","import type { GraphMetric } from \"../types.js\";\n\n/**\n * Coverage is a whole-suite DYNAMIC artifact — a function of *which tests ran*,\n * not of any file's bytes — so it must NOT ride the content-hash reuse gate. It\n * is emitted as a `coverage_pct` metric that is deliberately absent from every\n * *_METRIC_NAMES reuse set, so an incremental index never carries it forward: a\n * later index produces a snapshot with NO coverage until re-ingested. That is the\n * overlay semantics — coverage is attached to the snapshot it was measured\n * against and never inferred for another.\n */\nexport const COVERAGE_METRIC_NAME = \"coverage_pct\";\n\n/** Minimal Istanbul `coverage-final.json` shape we read (function-level). */\ninterface IstanbulFn {\n loc: { start: { line: number }; end: { line: number } };\n}\ninterface IstanbulFileCoverage {\n fnMap: Record<string, IstanbulFn>;\n /** Per-function hit counts, keyed to fnMap ids. */\n f: Record<string, number>;\n}\nexport type IstanbulCoverage = Record<string, IstanbulFileCoverage>;\n\n/** A symbol node's 1-based line span, for range-containment attribution. */\nexport interface SymbolSpan {\n id: string;\n startLine: number;\n endLine: number;\n}\n\nfunction isFileCoverage(v: unknown): v is IstanbulFileCoverage {\n return (\n typeof v === \"object\" &&\n v !== null &&\n typeof (v as IstanbulFileCoverage).fnMap === \"object\" &&\n typeof (v as IstanbulFileCoverage).f === \"object\"\n );\n}\n\n/** The smallest-span symbol whose 1-based range contains `line`, or null. */\nfunction innermostContaining(symbols: readonly SymbolSpan[], line: number): SymbolSpan | null {\n let best: SymbolSpan | null = null;\n for (const s of symbols) {\n if (s.startLine <= line && line <= s.endLine) {\n if (!best || s.endLine - s.startLine < best.endLine - best.startLine) best = s;\n }\n }\n return best;\n}\n\n/**\n * Attribute an Istanbul coverage report to graph nodes as `coverage_pct` metrics:\n * one per covered FILE (covered functions / total functions), and one per SYMBOL\n * a covered function maps into by RANGE containment (symbol spans) — matching\n * by range, not name, so anonymous/mangled Istanbul function names are handled.\n * A symbol spanning several functions (a class) reports its methods' coverage\n * ratio. Files Istanbul reports but the graph doesn't know are skipped.\n */\nexport function attributeCoverage(\n coverage: IstanbulCoverage,\n fileIdOf: (absPath: string) => string | null,\n symbolsByFile: ReadonlyMap<string, readonly SymbolSpan[]>,\n): GraphMetric[] {\n const out: GraphMetric[] = [];\n for (const [absPath, fc] of Object.entries(coverage)) {\n if (!isFileCoverage(fc)) continue;\n const fileId = fileIdOf(absPath);\n if (!fileId) continue;\n const fnIds = Object.keys(fc.fnMap);\n if (fnIds.length === 0) continue;\n\n const covered = fnIds.filter((k) => (fc.f[k] ?? 0) > 0).length;\n out.push(pctMetric(fileId, covered, fnIds.length));\n out.push(...symbolCoverage(fc, fnIds, symbolsByFile.get(fileId) ?? []));\n }\n return out;\n}\n\nfunction symbolCoverage(fc: IstanbulFileCoverage, fnIds: readonly string[], symbols: readonly SymbolSpan[]): GraphMetric[] {\n const perSymbol = new Map<string, { hit: number; total: number }>();\n for (const k of fnIds) {\n const sym = innermostContaining(symbols, fc.fnMap[k]!.loc.start.line);\n if (!sym) continue;\n const acc = perSymbol.get(sym.id) ?? { hit: 0, total: 0 };\n acc.total++;\n if ((fc.f[k] ?? 0) > 0) acc.hit++;\n perSymbol.set(sym.id, acc);\n }\n return [...perSymbol].map(([id, { hit, total }]) => pctMetric(id, hit, total));\n}\n\nfunction pctMetric(nodeId: string, covered: number, total: number): GraphMetric {\n return {\n nodeId,\n name: COVERAGE_METRIC_NAME,\n value: Math.round((100 * covered) / total),\n unit: \"percent\",\n };\n}\n","import type { Node, Point } from \"web-tree-sitter\";\nimport { parseFile } from \"@titan-design/code-parser\";\nimport { bodyStatements, descendantsOfType, pythonDocstring } from \"../comment-lines.js\";\n\nexport type MinifyLanguage = \"typescript\" | \"tsx\" | \"python\";\n\n/**\n * Minified source plus its line map. `lineMap[i]` is the 1-based original line\n * of output line `i + 1`; `originalLine` reads it by output line number.\n */\nexport interface MinifiedSource {\n text: string;\n lineMap: number[];\n}\n\ninterface OutputLine {\n text: string;\n line: number;\n /** A row inside a multi-line string: its whitespace is content, so it is neither trimmed nor collapsed. */\n verbatim: boolean;\n}\n\n/** A removed column range on one row; `pad` keeps the columns as spaces so code after a multi-line comment keeps its indent. */\ninterface Cut {\n from: number;\n to: number;\n pad: boolean;\n jsx: boolean;\n}\n\n/** A removed source range: a node, or a docstring with its trailing `;`. */\ninterface Span {\n start: Point;\n end: Point;\n jsx?: true;\n}\n\ninterface ImportBlock {\n startRow: number;\n endRow: number;\n count: number;\n}\n\nconst IMPORT_TYPES: Record<MinifyLanguage, ReadonlySet<string>> = {\n typescript: new Set([\"import_statement\"]),\n tsx: new Set([\"import_statement\"]),\n python: new Set([\"import_statement\", \"import_from_statement\", \"future_import_statement\"]),\n};\n\n/** Characters that end a token on their own, so nothing fuses across them. */\nconst DELIMITERS: ReadonlySet<string> = new Set([\"(\", \")\", \"[\", \"]\", \"{\", \"}\", \",\", \";\"]);\n\nconst STRING_TYPES: Record<MinifyLanguage, readonly string[]> = {\n typescript: [\"string\", \"template_string\"],\n tsx: [\"string\", \"template_string\"],\n python: [\"string\"],\n};\n\n/** The one line that stands in for a leading import block. */\nexport function importMarker(count: number, language: MinifyLanguage): string {\n const prefix = language === \"python\" ? \"#\" : \"//\";\n return `${prefix} … ${count} import${count === 1 ? \"\" : \"s\"}`;\n}\n\n/** The 1-based original line of a 1-based output line, or undefined past the end. */\nexport function originalLine(minified: MinifiedSource, outputLine: number): number | undefined {\n return minified.lineMap[outputLine - 1];\n}\n\nexport function isMinifyLanguage(language: string): language is MinifyLanguage {\n return language === \"typescript\" || language === \"tsx\" || language === \"python\";\n}\n\n/**\n * Safe-minify source for LLM context: drops comments and docstrings, strips\n * trailing whitespace, collapses blank-line runs and replaces a leading import\n * block with `importMarker`. It never renames or dedents, so every kept line is\n * its original line minus comments. Any other language comes back unchanged\n * with an identity line map.\n */\nexport async function minifySource(text: string, language: string): Promise<MinifiedSource> {\n if (!isMinifyLanguage(language)) return unchanged(text);\n const { tree } = await parseFile(text, \"source\", language);\n try {\n return minifyTree(tree.rootNode, text, language);\n } finally {\n tree.delete();\n }\n}\n\n/** The tree lives in WASM memory, so `minifySource` owns it and deletes it once this returns. */\nfunction minifyTree(root: Node, text: string, language: MinifyLanguage): MinifiedSource {\n const rows = text.split(\"\\n\");\n const cuts = cutsByRow(removedSpans(root, language));\n const verbatim = verbatimRows(root, language);\n const block = leadingImportBlock(root, language);\n const out: OutputLine[] = [];\n for (let row = 0; row < rows.length; row++) {\n if (block && row >= block.startRow && row <= block.endRow) {\n if (row === block.startRow) out.push({ text: importMarker(block.count, language), line: row + 1, verbatim: false });\n continue;\n }\n const kept = keepRow(rows[row] ?? \"\", cuts.get(row), verbatim.has(row));\n if (kept !== null) out.push({ text: kept, line: row + 1, verbatim: verbatim.has(row) });\n }\n return finish(collapseBlanks(out), text.endsWith(\"\\n\"));\n}\n\nfunction unchanged(text: string): MinifiedSource {\n const rows = text.split(\"\\n\");\n const count = text === \"\" ? 0 : text.endsWith(\"\\n\") ? rows.length - 1 : rows.length;\n return { text, lineMap: Array.from({ length: count }, (_, i) => i + 1) };\n}\n\nfunction removedSpans(root: Node, language: MinifyLanguage): Span[] {\n const comments = descendantsOfType(root, \"comment\");\n if (language !== \"python\") {\n return [\n ...[...comments, ...descendantsOfType(root, \"hash_bang_line\")].map(spanOf),\n ...jsxCommentExpressions(root).map((n) => ({ ...spanOf(n), jsx: true as const })),\n ];\n }\n return [...comments.map(spanOf), ...pythonDocstrings(root).map(docstringSpan)];\n}\n\nfunction spanOf(node: Node): Span {\n return { start: node.startPosition, end: node.endPosition };\n}\n\n/** `\"\"\"doc\"\"\";` alone on its row: the `;` goes with the docstring, or the row keeps a bare `;`. */\nfunction docstringSpan(docstring: Node): Span {\n const semicolon = docstring.nextSibling;\n const sameRow = semicolon?.type === \";\" && semicolon.startPosition.row === docstring.endPosition.row;\n return { start: docstring.startPosition, end: sameRow ? semicolon.endPosition : docstring.endPosition };\n}\n\n/** `{/* … *\\/}` in JSX: removing only the comment would leave an empty `{}` behind. */\nfunction jsxCommentExpressions(root: Node): Node[] {\n return descendantsOfType(root, \"jsx_expression\").filter(\n (n) => n.namedChildCount > 0 && n.namedChildren.every((c) => c?.type === \"comment\"),\n );\n}\n\nfunction pythonDocstrings(root: Node): Node[] {\n const bodies = [...descendantsOfType(root, \"class_definition\"), ...descendantsOfType(root, \"function_definition\")]\n .map((def) => def.childForFieldName(\"body\"))\n .filter((body): body is Node => body !== null);\n const docstrings = bodies.map((body) => droppableDocstring(body));\n const module = moduleDocstring(root);\n return [module && !sharesEndRow(module) ? module : null, ...docstrings].filter((d): d is Node => d !== null);\n}\n\n/** A docstring that is a body's only statement stays, or the body would be an empty suite. */\nfunction droppableDocstring(body: Node): Node | null {\n const docstring = pythonDocstring(body);\n if (!docstring || bodyStatements(body, docstring).length === 0) return null;\n return sharesEndRow(docstring) ? null : docstring;\n}\n\n/** `\"\"\"doc\"\"\"; x = 1`: dropping the docstring would leave a stray `;` before the statement. */\nfunction sharesEndRow(docstring: Node): boolean {\n let next = docstring.nextNamedSibling;\n while (next?.type === \"comment\") next = next.nextNamedSibling;\n return next?.startPosition.row === docstring.endPosition.row;\n}\n\n/** `pythonDocstring` reads a `block`; a module's docstring is the same leading string statement on the root. */\nfunction moduleDocstring(root: Node): Node | null {\n const first = root.namedChildren.find((c) => c !== null && c.type !== \"comment\");\n if (first?.type !== \"expression_statement\" || first.namedChildCount !== 1) return null;\n return first.namedChildren[0]?.type === \"string\" ? first : null;\n}\n\nfunction cutsByRow(spans: readonly Span[]): Map<number, Cut[]> {\n const cuts = new Map<number, Cut[]>();\n for (const { start, end, jsx } of spans) {\n for (let row = start.row; row <= end.row; row++) {\n const from = row === start.row ? start.column : 0;\n const to = row === end.row ? end.column : Number.MAX_SAFE_INTEGER;\n const list = cuts.get(row) ?? [];\n list.push({ from, to, pad: row !== start.row, jsx: jsx === true });\n cuts.set(row, list);\n }\n }\n return cuts;\n}\n\n/** Rows whose line break sits inside a string: the string's own content runs on past them. */\nfunction verbatimRows(root: Node, language: MinifyLanguage): Set<number> {\n const rows = new Set<number>();\n for (const type of STRING_TYPES[language]) {\n for (const s of descendantsOfType(root, type)) {\n for (let row = s.startPosition.row; row < s.endPosition.row; row++) rows.add(row);\n }\n }\n return rows;\n}\n\n/** The row with its cuts applied, or null when cuts left nothing but whitespace. */\nfunction keepRow(row: string, cuts: readonly Cut[] | undefined, verbatim: boolean): string | null {\n if (!cuts) return verbatim ? row : row.trimEnd();\n let kept = \"\";\n let cutSinceKept = false;\n let onlyJsxCut = true;\n for (let col = 0; col < row.length; col++) {\n const hits = cuts.filter((c) => col >= c.from && col < c.to);\n const char = row[col] ?? \"\";\n if (hits.length === 0) {\n const before = kept.at(-1) ?? \" \";\n if (cutSinceKept && wouldFuse(before, char) && !(onlyJsxCut && isTagEdge(before, char))) kept += \" \";\n kept += char;\n cutSinceKept = false;\n onlyJsxCut = true;\n } else if (hits.every((c) => c.pad)) kept += \" \";\n else {\n cutSinceKept = true;\n onlyJsxCut &&= hits.some((c) => c.jsx);\n }\n }\n const trimmed = kept.trimEnd();\n if (trimmed === \"\") return null;\n return verbatim ? kept : trimmed;\n}\n\n/** `typeof/**\\/x` or `a +/**\\/+b`: closing the gap would join two tokens into one, so one space stands in. */\nfunction wouldFuse(before: string, after: string): boolean {\n return /\\S/.test(before) && /\\S/.test(after) && !DELIMITERS.has(before) && !DELIMITERS.has(after);\n}\n\n/** A JSX child comment beside a tag edge: a space there would render as text, and no tokens can fuse across `>` or `<`. */\nfunction isTagEdge(before: string, after: string): boolean {\n return before === \">\" || after === \"<\";\n}\n\nfunction leadingImportBlock(root: Node, language: MinifyLanguage): ImportBlock | null {\n const children = root.namedChildren.filter((c): c is Node => c !== null);\n const docstring = language === \"python\" ? moduleDocstring(root) : null;\n let i = 0;\n while (i < children.length && isPreamble(children[i] as Node, docstring)) i++;\n const imports: Node[] = [];\n for (; i < children.length; i++) {\n const child = children[i] as Node;\n if (child.type === \"comment\") continue;\n if (!IMPORT_TYPES[language].has(child.type)) break;\n imports.push(child);\n }\n while (docstring && imports[0]?.startPosition.row === docstring.endPosition.row) imports.shift();\n const next = children[i];\n while (next && imports.length > 0 && imports[imports.length - 1]?.endPosition.row === next.startPosition.row) imports.pop();\n const first = imports[0];\n const last = imports[imports.length - 1];\n if (!first || !last) return null;\n return { startRow: first.startPosition.row, endRow: last.endPosition.row, count: imports.length };\n}\n\nfunction isPreamble(node: Node, docstring: Node | null): boolean {\n return node.type === \"comment\" || node.type === \"hash_bang_line\" || node.id === docstring?.id;\n}\n\n/** Collapses each blank run to one blank line and drops blanks at either end. */\nfunction collapseBlanks(lines: readonly OutputLine[]): OutputLine[] {\n const out: OutputLine[] = [];\n for (const line of lines) {\n const blank = line.text === \"\" && !line.verbatim;\n const prev = out[out.length - 1];\n if (blank && (!prev || (prev.text === \"\" && !prev.verbatim))) continue;\n out.push(line);\n }\n while (out.length > 0 && out[out.length - 1]?.text === \"\" && !out[out.length - 1]?.verbatim) out.pop();\n return out;\n}\n\nfunction finish(lines: readonly OutputLine[], trailingNewline: boolean): MinifiedSource {\n const body = lines.map((l) => l.text).join(\"\\n\");\n return {\n text: trailingNewline && lines.length > 0 ? `${body}\\n` : body,\n lineMap: lines.map((l) => l.line),\n };\n}\n","import { computePageRank, type PageRankOptions } from \"./pagerank.js\";\nimport type { GraphEdge, GraphNode } from \"../types.js\";\n\nexport interface RelevanceOptions {\n /** Probability of following an edge vs teleporting back to the seeds (default 0.85). */\n damping?: number;\n /** Per-kind edge weight override, forwarded to PageRank. */\n edgeWeights?: PageRankOptions[\"edgeWeights\"];\n}\n\n/**\n * C-89 — **seeded (personalized) PageRank as a relevance-to-target proximity\n * measure** (Aider RepoMap-style). The teleport vector is concentrated on\n * `seedIds`, so the stationary distribution scores every node by how tightly it\n * couples to the seeds through the resolved dependency graph: near neighbours\n * score high, decaying with graph distance. This is \"relevance to what I'm\n * looking at,\" distinct from global PageRank centrality (\"globally famous\"),\n * which stays the no-seed cold path.\n *\n * The edge set is **symmetrized** (each edge added in both directions) so\n * relevance flows to a target's callers AND its dependencies — a purely forward\n * walk from the seed would only reach what the seed depends on, never who\n * depends on it. Edge kind (and therefore weight) is preserved on the reversed\n * copy, so a heavier `calls` edge stays heavier in both directions.\n *\n * Returns a Map from node id to relevance score (seeds included). An empty seed\n * set returns an empty map — callers then fall back to global centrality.\n */\nexport function computeRelevance(\n nodes: readonly GraphNode[],\n edges: readonly GraphEdge[],\n seedIds: readonly string[],\n options: RelevanceOptions = {},\n): Map<string, number> {\n const seeds = seedIds.filter((id) => id.length > 0);\n if (seeds.length === 0) return new Map();\n const personalization = new Map(seeds.map((id) => [id, 1] as const));\n const result = computePageRank(nodes, symmetrize(edges), {\n personalization,\n damping: options.damping,\n edgeWeights: options.edgeWeights,\n });\n const out = new Map<string, number>();\n for (const row of result.rows) out.set(row.nodeId, row.score);\n return out;\n}\n\n/** Every edge plus its reverse, so the relevance walk is bidirectional. */\nfunction symmetrize(edges: readonly GraphEdge[]): GraphEdge[] {\n const out: GraphEdge[] = [];\n for (const e of edges) {\n out.push(e);\n out.push({ ...e, srcId: e.dstId, dstId: e.srcId });\n }\n return out;\n}\n","import { parseSymbolId } from \"../../extractors/ids.js\";\nimport type { GraphNode } from \"../../types.js\";\n\n/** Marks a gap between two symbols that are not adjacent in their file. */\nexport const ELISION_MARKER = \"...\";\n/** Ends a line cut at `maxLineChars`; it counts toward the limit. */\nexport const TRUNCATION_SUFFIX = \"…\";\nexport const DEFAULT_MAX_LINE_CHARS = 120;\n\nconst INDENT = \" \";\n\nexport interface SignatureTreeOptions {\n maxLineChars?: number;\n}\n\ninterface Entry {\n node: GraphNode;\n start?: number;\n end?: number;\n depth: number;\n}\n\n/**\n * Render symbols as a signatures-only tree for LLM context: per file (sorted by\n * path) a header line, then one line per symbol, with `ELISION_MARKER` between\n * symbols that are not adjacent. Pure; output is independent of input order.\n *\n * A line is the symbol's `attrs.signature`, else `<name> (<kind>)`. Symbols\n * order by `attrs.startLine`, then name, then id. A qualified name\n * (`Job.run`) indents one level per dot. Symbols with no `startLine`\n * (exported types and consts) render after the line-ordered ones, sorted by\n * name then id, and get no elision markers because their position is unknown.\n */\nexport function renderSignatureTree(\n nodes: readonly GraphNode[],\n options: SignatureTreeOptions = {},\n): string {\n const max = options.maxLineChars ?? DEFAULT_MAX_LINE_CHARS;\n const lines: string[] = [];\n for (const [file, entries] of groupByFile(nodes)) {\n lines.push(truncate(file, max));\n for (const line of fileLines(entries)) lines.push(truncate(line, max));\n }\n return lines.join(\"\\n\");\n}\n\nfunction groupByFile(nodes: readonly GraphNode[]): [string, Entry[]][] {\n const byFile = new Map<string, Entry[]>();\n for (const node of nodes) {\n if (node.kind !== \"symbol\") continue;\n const parsed = parseSymbolId(node.id);\n const file = node.parentId ?? parsed?.fileId ?? node.id;\n const list = byFile.get(file) ?? [];\n list.push(toEntry(node, parsed?.name ?? node.name));\n byFile.set(file, list);\n }\n return [...byFile].sort(([a], [b]) => compare(a, b));\n}\n\nfunction toEntry(node: GraphNode, qualifiedName: string): Entry {\n const start = numberAttr(node, \"startLine\");\n const end = numberAttr(node, \"endLine\") ?? start;\n return { node, start, end, depth: qualifiedName.split(\".\").length - 1 };\n}\n\nfunction numberAttr(node: GraphNode, key: string): number | undefined {\n const value = node.attrs?.[key];\n return typeof value === \"number\" ? value : undefined;\n}\n\nfunction fileLines(entries: Entry[]): string[] {\n const ordered = entries.sort(compareEntries);\n const lines: string[] = [];\n let reach: number | undefined;\n for (const entry of ordered) {\n if (reach !== undefined && entry.start !== undefined && !adjacent(reach, entry.start)) {\n lines.push(ELISION_MARKER);\n }\n lines.push(INDENT.repeat(entry.depth) + symbolText(entry.node));\n if (entry.end !== undefined) reach = Math.max(reach ?? entry.end, entry.end);\n }\n return lines;\n}\n\n/** Adjacent: the next symbol starts at most one line after the furthest end so far. */\nfunction adjacent(reach: number, nextStart: number): boolean {\n return nextStart <= reach + 1;\n}\n\nfunction symbolText(node: GraphNode): string {\n const signature = node.attrs?.signature;\n const text =\n typeof signature === \"string\" && signature !== \"\"\n ? signature\n : `${node.name} (${node.kind})`;\n return text.replace(/\\s*\\n\\s*/g, \" \");\n}\n\nfunction compareEntries(a: Entry, b: Entry): number {\n if (a.start !== b.start) {\n if (a.start === undefined) return 1;\n if (b.start === undefined) return -1;\n return a.start - b.start;\n }\n return compare(a.node.name, b.node.name) || compare(a.node.id, b.node.id);\n}\n\nfunction compare(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\nfunction truncate(line: string, max: number): string {\n if (line.length <= max) return line;\n if (max <= TRUNCATION_SUFFIX.length) return TRUNCATION_SUFFIX.slice(0, Math.max(max, 0));\n return line.slice(0, max - TRUNCATION_SUFFIX.length) + TRUNCATION_SUFFIX;\n}\n","import { parseSymbolId } from \"../../extractors/ids.js\";\nimport type { GraphNode } from \"../../types.js\";\nimport {\n buildBlastRadius,\n collectSymbolUtil,\n type BlastRadiusEntry,\n type NodeMetrics,\n type SymbolUtil,\n} from \"../dashboard-node-metrics.js\";\nimport {\n computeSymbolConsumers,\n computeSymbolCoupling,\n type ReferenceEdgeLite,\n} from \"../symbol-coupling.js\";\n\n/**\n * C-74 — deterministic per-file / per-symbol **context dossier** (Class A). A\n * pure projection of the already-computed graph: no LLM, no source re-parse. The\n * command layer (graph-context.ts) loads the snapshot and hands the assembled\n * inputs here; this module owns only the shaping + the markdown render, so it is\n * unit-testable on synthetic graphs.\n */\n\n/** Bumped when the dossier shape changes, so a RAG store can invalidate records. */\nexport const SCHEMA_VERSION = \"2\";\n\nexport interface Provenance {\n snapshotId: number;\n ref: string;\n commitHash: string | null;\n takenAt: string;\n indexVersion: string;\n}\n\n/** `references` edges resolve cross-file imports only — flagged so a RAG query doesn't over-trust the count. */\nconst CONSUMER_NOTE =\n \"cross-file import resolution only; intra-file and dynamic import() callers are excluded\";\n\n/**\n * Consumers split by declaring-file role (C-74/G3): for core exports most inbound\n * references are test files, which is truthful but low-signal for \"what production\n * code depends on this\" — so source and test consumers are separated, not flattened.\n */\nexport interface Consumers {\n source: string[];\n test: string[];\n counts: { source: number; test: number; total: number };\n note: string;\n}\n\nfunction splitConsumers(\n files: readonly string[],\n roleByFile: ReadonlyMap<string, string>,\n): Consumers {\n const source: string[] = [];\n const test: string[] = [];\n for (const f of files) (roleByFile.get(f) === \"test\" ? test : source).push(f);\n return {\n source,\n test,\n counts: { source: source.length, test: test.length, total: files.length },\n note: CONSUMER_NOTE,\n };\n}\n\nexport interface FileOwnership {\n primaryOwner: string;\n busFactor: number;\n authorCount: number;\n}\n\n/** One of a file's declared symbols, projected for the dossier. */\nexport interface SymbolLine {\n name: string;\n exported: boolean;\n /** One-line type signature (C-79), when indexed for this declaration. */\n signature?: string;\n cognitive?: number;\n cyclomatic?: number;\n utilization: number;\n /** Distinct files that reference this symbol (inbound `references`). */\n consumers: number;\n /**\n * Symbol-level importance (C-89): the declaring file's PageRank centrality\n * redistributed across its symbols by utilization share, so a graph-central\n * file's rank lands on the definitions actually carrying its inbound use.\n */\n importance?: number;\n}\n\nexport interface SymbolDossier {\n exported: boolean;\n /** G1 slot — the one-line type signature indexed from `attrs.signature` (C-79); null when unannotated or unresolvable. */\n signature: string | null;\n /** G2 slot — leading docstring / intent. Null today. */\n purpose: string | null;\n complexity: { cognitive?: number; cyclomatic?: number };\n utilization: number;\n consumers: Consumers;\n blastRadius: number;\n coupledWith: { symbolId: string; name: string; fileId: string; coImports: number }[];\n}\n\nexport interface FileDossier {\n metrics: NodeMetrics;\n churn: { windowDays: number; value: number } | null;\n centrality: number;\n ownership: FileOwnership | null;\n symbols: SymbolLine[];\n dependsOn: string[];\n consumers: Consumers;\n blastRadius: BlastRadiusEntry[];\n}\n\nexport interface ContextDossier {\n schemaVersion: string;\n target: {\n id: string;\n kind: \"file\" | \"symbol\";\n name: string;\n path: string;\n span?: { startLine: number; endLine: number };\n };\n provenance: Provenance;\n symbol?: SymbolDossier;\n file?: FileDossier;\n notes: string[];\n}\n\nexport interface ContextBuildInput {\n target: GraphNode;\n kind: \"file\" | \"symbol\";\n provenance: Provenance;\n /** All nodes for the snapshot, symbols INCLUDED. */\n nodes: readonly GraphNode[];\n /** `references` edges as {srcId=importing file, dstId=symbol id}. */\n refEdges: readonly ReferenceEdgeLite[];\n /** `imports` edges as {srcId, dstId} (file → file/external). */\n importEdges: readonly { srcId: string; dstId: string }[];\n metrics: ReadonlyMap<string, NodeMetrics>;\n churnByFile: ReadonlyMap<string, number>;\n churnWindowDays: number;\n centrality: ReadonlyMap<string, number>;\n ownership: ReadonlyMap<string, FileOwnership> | null;\n /** File id → node role, for splitting consumers into source vs test (G3). */\n roleByFile: ReadonlyMap<string, string>;\n}\n\n/** Number of distinct importing files per symbol id (inbound `references`). */\nfunction consumerCounts(\n edges: readonly ReferenceEdgeLite[],\n): Map<string, string[]> {\n const out = new Map<string, string[]>();\n for (const c of computeSymbolConsumers(edges)) out.set(c.symbolId, c.consumers);\n return out;\n}\n\nfunction fileIdOf(symbolId: string): string | null {\n return parseSymbolId(symbolId)?.fileId ?? null;\n}\n\nfunction buildSymbolDossier(input: ContextBuildInput): SymbolDossier {\n const id = input.target.id;\n const parsed = parseSymbolId(id);\n const fileId = parsed?.fileId ?? \"\";\n const m = input.metrics.get(id);\n const consumers = consumerCounts(input.refEdges).get(id) ?? [];\n const complexity = m?.cognitiveMax ?? input.metrics.get(fileId)?.cognitiveMax ?? 0;\n const churn = input.churnByFile.get(fileId) ?? 0;\n const coupledWith = computeSymbolCoupling(input.refEdges)\n .filter((p) => p.aId === id || p.bId === id)\n .map((p) => (p.aId === id ? partner(p.bId, p.bName, p.bFile, p.coImports) : partner(p.aId, p.aName, p.aFile, p.coImports)))\n .slice(0, 15);\n return {\n exported: input.target.attrs?.exported !== false,\n signature: attrString(input.target.attrs?.signature),\n purpose: attrString(input.target.attrs?.purpose),\n complexity: { cognitive: m?.cognitiveMax, cyclomatic: m?.cyclomaticMax },\n utilization: m?.utilization ?? 0,\n consumers: splitConsumers(consumers, input.roleByFile),\n blastRadius: (m?.utilization ?? 0) * complexity * churn,\n coupledWith,\n };\n}\n\nfunction partner(symbolId: string, name: string, fileId: string, coImports: number) {\n return { symbolId, name, fileId, coImports };\n}\n\n/** A string symbol attr (signature/purpose, C-79) or null when not indexed. */\nfunction attrString(value: unknown): string | null {\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\n/** File's declared symbols, exports first (by utilization) then internals (by complexity). */\nfunction fileSymbols(\n fileId: string,\n nodes: readonly GraphNode[],\n metrics: ReadonlyMap<string, NodeMetrics>,\n consumers: ReadonlyMap<string, string[]>,\n): SymbolLine[] {\n const lines: (SymbolLine & { rank: number })[] = [];\n for (const n of nodes) {\n if (n.kind !== \"symbol\" || n.parentId !== fileId) continue;\n const m = metrics.get(n.id);\n const exported = n.attrs?.exported !== false;\n lines.push({\n name: n.name,\n exported,\n signature: attrString(n.attrs?.signature) ?? undefined,\n cognitive: m?.cognitiveMax,\n cyclomatic: m?.cyclomaticMax,\n utilization: m?.utilization ?? 0,\n consumers: (consumers.get(n.id) ?? []).length,\n rank: exported ? (m?.utilization ?? 0) : -(m?.cognitiveMax ?? 0),\n });\n }\n return sortSymbols(lines);\n}\n\nfunction sortSymbols(lines: (SymbolLine & { rank: number })[]): SymbolLine[] {\n const exported = lines\n .filter((l) => l.exported)\n .sort((a, b) => b.utilization - a.utilization || (b.cognitive ?? 0) - (a.cognitive ?? 0));\n const internal = lines\n .filter((l) => !l.exported)\n .sort((a, b) => (b.cognitive ?? 0) - (a.cognitive ?? 0) || a.name.localeCompare(b.name));\n return [...exported, ...internal].map(({ rank: _rank, ...line }) => line);\n}\n\n/**\n * Split the declaring file's centrality across its symbols proportional to each\n * symbol's utilization (C-89) — the file's graph importance flows onto the\n * definitions that actually carry its inbound use. When no symbol is used\n * (Σutil = 0) there is no basis to redistribute, so importance is left unset.\n */\nfunction redistributeImportance(symbols: SymbolLine[], fileCentrality: number): SymbolLine[] {\n const totalUtil = symbols.reduce((sum, s) => sum + s.utilization, 0);\n if (totalUtil <= 0 || fileCentrality <= 0) return symbols;\n return symbols.map((s) => ({\n ...s,\n importance: Math.round(fileCentrality * (s.utilization / totalUtil) * 1e6) / 1e6,\n }));\n}\n\nfunction fileConsumers(fileId: string, refEdges: readonly ReferenceEdgeLite[]): string[] {\n const set = new Set<string>();\n for (const e of refEdges) if (fileIdOf(e.dstId) === fileId) set.add(e.srcId);\n return [...set].sort();\n}\n\nfunction fileDependsOn(\n fileId: string,\n refEdges: readonly ReferenceEdgeLite[],\n importEdges: readonly { srcId: string; dstId: string }[],\n): string[] {\n const set = new Set<string>();\n for (const e of refEdges) if (e.srcId === fileId) { const f = fileIdOf(e.dstId); if (f) set.add(f); }\n for (const e of importEdges) if (e.srcId === fileId) set.add(e.dstId);\n set.delete(fileId);\n return [...set].sort();\n}\n\nfunction buildFileDossier(input: ContextBuildInput): FileDossier {\n const fileId = input.target.id;\n const consumers = consumerCounts(input.refEdges);\n const symbolUtil: SymbolUtil[] = collectSymbolUtil(input.nodes, input.metrics).filter((s) => s.fileId === fileId);\n const churnValue = input.churnByFile.get(fileId);\n const centrality = input.centrality.get(fileId) ?? 0;\n return {\n metrics: input.metrics.get(fileId) ?? {},\n churn: churnValue === undefined ? null : { windowDays: input.churnWindowDays, value: churnValue },\n centrality,\n ownership: input.ownership?.get(fileId) ?? null,\n symbols: redistributeImportance(\n fileSymbols(fileId, input.nodes, input.metrics, consumers),\n centrality,\n ),\n dependsOn: fileDependsOn(fileId, input.refEdges, input.importEdges),\n consumers: splitConsumers(fileConsumers(fileId, input.refEdges), input.roleByFile),\n blastRadius: buildBlastRadius(symbolUtil, input.metrics, input.churnByFile, 15),\n };\n}\n\nconst SIGNATURE_NOTE =\n \"Type signatures and docstrings are indexed for resolvable TypeScript declarations (C-79); a null signature means it was unannotated or unresolvable — open target.path at target.span.\";\n\nexport function buildContextDossier(input: ContextBuildInput): ContextDossier {\n const { target, kind } = input;\n const span = readSpan(target);\n const path = kind === \"symbol\" ? (parseSymbolId(target.id)?.fileId ?? target.id) : target.id;\n const notes: string[] = [SIGNATURE_NOTE];\n if (kind === \"file\" && input.ownership === null) {\n notes.push(\"Ownership omitted (git-derived; run without --no-ownership on a repo checkout).\");\n }\n return {\n schemaVersion: SCHEMA_VERSION,\n target: { id: target.id, kind, name: target.name, path, span },\n provenance: input.provenance,\n symbol: kind === \"symbol\" ? buildSymbolDossier(input) : undefined,\n file: kind === \"file\" ? buildFileDossier(input) : undefined,\n notes,\n };\n}\n\nfunction readSpan(node: GraphNode): { startLine: number; endLine: number } | undefined {\n const start = node.attrs?.startLine;\n const end = node.attrs?.endLine;\n if (typeof start === \"number\" && typeof end === \"number\") return { startLine: start, endLine: end };\n return undefined;\n}\n","import type {\n Consumers,\n ContextDossier,\n FileDossier,\n SymbolDossier,\n} from \"./dossier.js\";\n\n/**\n * Human/agent-readable markdown projection of a {@link ContextDossier} (C-74).\n * The JSON form is the RAG-store record; this is the same facts rendered for a\n * reader (or an agent that prefers prose). Deterministic — no LLM.\n */\nexport function renderContextMarkdown(d: ContextDossier): string {\n const span = d.target.span ? `:${d.target.span.startLine}-${d.target.span.endLine}` : \"\";\n const lines = [\n `# ${d.target.kind === \"symbol\" ? d.target.name : d.target.path}`,\n \"\",\n `- **kind**: ${d.target.kind}`,\n `- **path**: \\`${d.target.path}${span}\\``,\n `- **snapshot**: ${d.provenance.ref} (${d.provenance.commitHash ?? \"—\"}) @ ${d.provenance.takenAt}`,\n \"\",\n ];\n if (d.symbol) lines.push(...renderSymbol(d.symbol));\n if (d.file) lines.push(...renderFile(d.file));\n if (d.notes.length) lines.push(\"## Notes\", ...d.notes.map((n) => `- ${n}`), \"\");\n return lines.join(\"\\n\");\n}\n\nfunction renderSymbol(s: SymbolDossier): string[] {\n const out = [\n \"## Symbol\",\n `- **exported**: ${s.exported}`,\n `- **signature**: ${s.signature ? `\\`${s.signature}\\`` : \"— (not indexed)\"}`,\n `- **purpose**: ${s.purpose ?? \"—\"}`,\n `- **complexity**: cognitive ${s.complexity.cognitive ?? \"—\"}, cyclomatic ${s.complexity.cyclomatic ?? \"—\"}`,\n `- **utilization**: ${s.utilization}`,\n `- **blast radius**: ${round(s.blastRadius)}`,\n ...renderConsumers(s.consumers),\n ];\n if (s.coupledWith.length) {\n out.push(\"### Co-imported with\");\n for (const c of s.coupledWith) out.push(`- ${c.name} (\\`${c.fileId}\\`) ×${c.coImports}`);\n out.push(\"\");\n }\n return out;\n}\n\nfunction renderFile(f: FileDossier): string[] {\n const m = f.metrics;\n const own = f.ownership\n ? `${f.ownership.primaryOwner} (bus factor ${f.ownership.busFactor}, ${f.ownership.authorCount} authors)`\n : \"—\";\n const out = [\n \"## File\",\n `- **loc**: ${m.loc ?? \"—\"} · **cognitive** ${m.cognitiveMax ?? \"—\"} · **cyclomatic** ${m.cyclomaticMax ?? \"—\"}`,\n `- **fan-in/out**: ${m.fanIn ?? \"—\"} / ${m.fanOut ?? \"—\"} · **centrality**: ${round(f.centrality)}`,\n `- **churn**: ${f.churn ? `${f.churn.value} (${f.churn.windowDays}d)` : \"—\"} · **role**: ${m.role ?? \"—\"}`,\n `- **ownership**: ${own}`,\n \"\",\n ...section(`Depends on (${f.dependsOn.length})`, f.dependsOn),\n ...renderConsumers(f.consumers),\n ];\n if (f.symbols.length) {\n out.push(`### Symbols (${f.symbols.length})`);\n for (const s of f.symbols) {\n const tag = s.exported ? \"export\" : \"internal\";\n const sig = s.signature ? ` \\`${s.signature}\\`` : \"\";\n const imp = s.importance !== undefined ? `, importance ${s.importance}` : \"\";\n out.push(`- \\`${s.name}\\` (${tag})${sig} — util ${s.utilization}, cog ${s.cognitive ?? \"—\"}, consumers ${s.consumers}${imp}`);\n }\n out.push(\"\");\n }\n if (f.blastRadius.length) {\n out.push(\"### Blast radius (look here first)\");\n for (const b of f.blastRadius) out.push(`- \\`${b.name}\\` — score ${round(b.score)} (util ${b.utilization} × cog ${b.complexity} × churn ${b.churn})`);\n out.push(\"\");\n }\n return out;\n}\n\nfunction section(title: string, items: readonly string[]): string[] {\n if (!items.length) return [];\n return [`### ${title}`, ...items.map((i) => `- \\`${i}\\``), \"\"];\n}\n\n/** Source consumers lead (the actionable set); test consumers are counted, not listed. */\nfunction renderConsumers(c: Consumers): string[] {\n const header = `### Consumers — ${c.counts.source} source, ${c.counts.test} test (${c.counts.total} total)`;\n const rows = c.source.map((i) => `- \\`${i}\\``);\n return [header, ...(rows.length ? rows : [\"- (no non-test consumers)\"]), `> ${c.note}`, \"\"];\n}\n\nfunction round(n: number): number {\n return Math.round(n * 1000) / 1000;\n}\n","import { readFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { parseSymbolId } from \"../../extractors/ids.js\";\nimport type { GraphEdge, GraphNode } from \"../../types.js\";\nimport type { ContextDossier } from \"./dossier.js\";\nimport { renderContextMarkdown } from \"./format.js\";\n\n/**\n * C-80 — the **context bundle**: one deterministic pull of the complete paired\n * context for a symbol/file, the push half of the ingestion API. It wraps the\n * C-74 dossier with the three things an ingestor needs to embed/answer WITHOUT\n * opening the file: the raw **source chunk** (source text of the span), the\n * resolved **graph linkages as explicit edges** (callers / dependencies /\n * coupled-with — not just counts), and **coverage** (C-63, when the overlay is\n * ingested). No LLM; a pure projection of the graph + the working-tree source.\n */\nexport const BUNDLE_SCHEMA_VERSION = \"2\";\n\nexport interface SourceChunk {\n /** Repo-relative file id the chunk was read from. */\n path: string;\n /** 1-based inclusive line span for a symbol; null for a whole-file target. */\n span: { startLine: number; endLine: number } | null;\n /** The source text, or null when the file could not be read. */\n text: string | null;\n note?: string;\n}\n\n/** A resolved graph linkage, deterministic and directional relative to the target. */\nexport interface BundleEdge {\n from: string;\n to: string;\n kind: string;\n weight: number;\n /**\n * Seeded-PageRank relevance of this edge's neighbour to the target (C-89).\n * Present only when the target was seeded (the bundle path); the neighbour is\n * whichever endpoint is not the target's file. Edges are ordered by it, so the\n * most target-relevant linkages lead, not the globally-famous ones.\n */\n relevance?: number;\n}\n\nexport interface BundleEdges {\n /** Inbound — who references/imports the target. */\n callers: BundleEdge[];\n /** Outbound — what the target references/imports. */\n dependencies: BundleEdge[];\n /** Co-import coupling partners (symbol targets only). */\n coupledWith: BundleEdge[];\n note: string;\n}\n\nexport interface Coverage {\n pct: number | null;\n note?: string;\n}\n\nexport interface ContextBundle {\n schemaVersion: string;\n dossier: ContextDossier;\n source: SourceChunk;\n edges: BundleEdges;\n coverage: Coverage;\n}\n\nexport interface BundleBuildInput {\n dossier: ContextDossier;\n target: GraphNode;\n kind: \"file\" | \"symbol\";\n /** Weighted `references` edges (srcId = importing file → dstId = symbol id). */\n refEdges: readonly GraphEdge[];\n /** Weighted `imports` edges (file → file/external). */\n importEdges: readonly GraphEdge[];\n /** Git toplevel to resolve the source path, or null (read relative to cwd). */\n repoRoot: string | null;\n /** `coverage_pct` for the target node, or null when the overlay is absent. */\n coveragePct: number | null;\n /** File id → seeded-relevance score (C-89); absent/empty ⇒ weight-ordered cold path. */\n relevanceByFile?: ReadonlyMap<string, number>;\n /** The target's declaring file id, for locating each edge's neighbour (C-89). */\n targetFileId?: string;\n}\n\nconst EDGE_NOTE =\n \"references resolve cross-file import usage (src = importing file → dst = symbol); a symbol's dependencies are its declaring file's outbound edges (the graph resolves the source side at file granularity).\";\nconst COVERAGE_NOTE =\n \"coverage_pct overlay not ingested; run `graph coverage <istanbul-report>` to populate.\";\nconst SOURCE_READ_NOTE = \"source file could not be read from the working tree at this path.\";\n\nfunction weightOf(e: GraphEdge): number {\n const w = e.attrs?.weight;\n return typeof w === \"number\" ? w : 1;\n}\n\n/** Seeded-relevance ranking context, or null on the no-seed cold path. */\ninterface RelevanceCtx {\n relevanceByFile: ReadonlyMap<string, number>;\n targetFileId: string;\n}\n\nfunction relevanceCtx(input: BundleBuildInput): RelevanceCtx | null {\n const { relevanceByFile, targetFileId } = input;\n if (!relevanceByFile || relevanceByFile.size === 0 || targetFileId === undefined) return null;\n return { relevanceByFile, targetFileId };\n}\n\n/** File that declares a node (itself for a file, its parent for a symbol). */\nfunction fileOf(id: string): string {\n return parseSymbolId(id)?.fileId ?? id;\n}\n\n/**\n * Order the edges. With a seed (bundle path) rank by relevance-to-target — the\n * seeded-PageRank score of whichever endpoint is not the target's file — so the\n * closest linkages lead; without one, fall back to raw edge weight (global fame).\n */\nfunction rankEdges(edges: BundleEdge[], ctx: RelevanceCtx | null): BundleEdge[] {\n if (!ctx) return sortByWeight(edges);\n const annotated = edges.map((e) => {\n const neighbor = fileOf(e.from) === ctx.targetFileId ? fileOf(e.to) : fileOf(e.from);\n return { ...e, relevance: round4(ctx.relevanceByFile.get(neighbor) ?? 0) };\n });\n return annotated.sort(\n (a, b) =>\n (b.relevance ?? 0) - (a.relevance ?? 0) ||\n b.weight - a.weight ||\n a.from.localeCompare(b.from) ||\n a.to.localeCompare(b.to),\n );\n}\n\nfunction sortByWeight(edges: BundleEdge[]): BundleEdge[] {\n return edges.sort(\n (a, b) => b.weight - a.weight || a.from.localeCompare(b.from) || a.to.localeCompare(b.to),\n );\n}\n\nfunction round4(n: number): number {\n return Math.round(n * 1e6) / 1e6;\n}\n\n/** Explicit resolved edges for a symbol target: inbound refs, its file's outbound refs, coupling. */\nfunction symbolEdges(input: BundleBuildInput): BundleEdges {\n const id = input.target.id;\n const fileId = parseSymbolId(id)?.fileId ?? \"\";\n const ctx = relevanceCtx(input);\n const callers = input.refEdges\n .filter((e) => e.dstId === id)\n .map((e) => ({ from: e.srcId, to: id, kind: \"references\", weight: weightOf(e) }));\n const dependencies = [\n ...input.refEdges.filter((e) => e.srcId === fileId).map((e) => edge(e, \"references\")),\n ...input.importEdges.filter((e) => e.srcId === fileId).map((e) => edge(e, \"imports\")),\n ];\n const coupledWith = (input.dossier.symbol?.coupledWith ?? []).map((c) => ({\n from: id,\n to: c.symbolId,\n kind: \"coupled-with\",\n weight: c.coImports,\n }));\n return {\n callers: rankEdges(callers, ctx),\n dependencies: rankEdges(dependencies, ctx),\n coupledWith: rankEdges(coupledWith, ctx),\n note: EDGE_NOTE,\n };\n}\n\n/** Explicit resolved edges for a file target: inbound + outbound refs and imports. */\nfunction fileEdges(input: BundleBuildInput): BundleEdges {\n const id = input.target.id;\n const ctx = relevanceCtx(input);\n const inbound = (e: GraphEdge) => parseSymbolId(e.dstId)?.fileId === id;\n const callers = [\n ...input.refEdges.filter(inbound).map((e) => edge(e, \"references\")),\n ...input.importEdges.filter((e) => e.dstId === id).map((e) => edge(e, \"imports\")),\n ];\n const dependencies = [\n ...input.refEdges.filter((e) => e.srcId === id).map((e) => edge(e, \"references\")),\n ...input.importEdges.filter((e) => e.srcId === id).map((e) => edge(e, \"imports\")),\n ];\n return {\n callers: rankEdges(callers, ctx),\n dependencies: rankEdges(dependencies, ctx),\n coupledWith: [],\n note: EDGE_NOTE,\n };\n}\n\nfunction edge(e: GraphEdge, kind: string): BundleEdge {\n return { from: e.srcId, to: e.dstId, kind, weight: weightOf(e) };\n}\n\nfunction readSource(input: BundleBuildInput): SourceChunk {\n const filePath =\n input.kind === \"symbol\" ? (parseSymbolId(input.target.id)?.fileId ?? input.target.id) : input.target.id;\n const span = input.dossier.target.span ?? null;\n const abs = input.repoRoot ? path.join(input.repoRoot, filePath) : filePath;\n try {\n const content = readFileSync(abs, \"utf8\");\n const text = span ? sliceSpan(content, span) : content;\n return { path: filePath, span, text };\n } catch {\n return { path: filePath, span, text: null, note: SOURCE_READ_NOTE };\n }\n}\n\n/** 1-based inclusive line slice. */\nfunction sliceSpan(content: string, span: { startLine: number; endLine: number }): string {\n return content.split(\"\\n\").slice(span.startLine - 1, span.endLine).join(\"\\n\");\n}\n\nexport function buildContextBundle(input: BundleBuildInput): ContextBundle {\n return {\n schemaVersion: BUNDLE_SCHEMA_VERSION,\n dossier: input.dossier,\n source: readSource(input),\n edges: input.kind === \"symbol\" ? symbolEdges(input) : fileEdges(input),\n coverage: {\n pct: input.coveragePct,\n note: input.coveragePct === null ? COVERAGE_NOTE : undefined,\n },\n };\n}\n\n/** Concatenated text projection — hand this straight to an embedder/LLM. */\nexport function renderBundleText(bundle: ContextBundle): string {\n const cov = bundle.coverage.pct === null ? \"—\" : `${bundle.coverage.pct}%`;\n return [\n renderContextMarkdown(bundle.dossier),\n \"## Coverage\",\n `- **coverage**: ${cov}`,\n \"\",\n ...renderEdgeSection(\"Callers (inbound)\", bundle.edges.callers),\n ...renderEdgeSection(\"Dependencies (outbound)\", bundle.edges.dependencies),\n ...renderEdgeSection(\"Coupled with\", bundle.edges.coupledWith),\n \"## Source\",\n \"```typescript\",\n bundle.source.text ?? `// ${bundle.source.note ?? \"unavailable\"}`,\n \"```\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction renderEdgeSection(title: string, edges: readonly BundleEdge[]): string[] {\n if (!edges.length) return [];\n return [`### ${title}`, ...edges.map(renderEdgeLine), \"\"];\n}\n\nfunction renderEdgeLine(e: BundleEdge): string {\n const rel = e.relevance !== undefined ? `, rel ${e.relevance}` : \"\";\n return `- \\`${e.from}\\` → \\`${e.to}\\` (${e.kind} ×${e.weight}${rel})`;\n}\n","import type { CodeGraphStore } from \"../store.js\";\nimport { computePageRank, type PageRankOptions, type PageRankResult } from \"./pagerank.js\";\nimport { computeRelevance, type RelevanceOptions } from \"./relevance.js\";\nimport {\n computeSymbolConsumers,\n computeSymbolCoupling,\n type ReferenceEdgeLite,\n type SymbolConsumers,\n type SymbolCouplingOptions,\n type SymbolCouplingPair,\n} from \"./symbol-coupling.js\";\n\n/**\n * PageRank over one snapshot's file-level graph (symbol nodes and `references`\n * edges excluded, as codewatch's `graph relevant` reads it). Pass\n * `personalization` to seed the walk toward target node ids.\n */\nexport function snapshotPageRank(\n store: CodeGraphStore,\n snapshotId: number,\n options: PageRankOptions = {},\n): PageRankResult {\n // The store reads rows unordered, so float-tied scores may order differently than in codewatch.\n return computePageRank(store.listNodes(snapshotId), store.listEdges(snapshotId), options);\n}\n\n/** Relevance of every file-level node to `seedIds`, as codewatch's `graph context` computes it. */\nexport function snapshotRelevance(\n store: CodeGraphStore,\n snapshotId: number,\n seedIds: readonly string[],\n options: RelevanceOptions = {},\n): Map<string, number> {\n return computeRelevance(store.listNodes(snapshotId), store.listEdges(snapshotId), seedIds, options);\n}\n\n/** The snapshot's `references` edges: importing file to imported symbol. */\nexport function snapshotReferenceEdges(store: CodeGraphStore, snapshotId: number): ReferenceEdgeLite[] {\n return store\n .listEdges(snapshotId, { includeReferences: true })\n .filter((e) => e.kind === \"references\")\n .map((e) => ({ srcId: e.srcId, dstId: e.dstId }));\n}\n\n/** Per-symbol consumer files for one snapshot. */\nexport function snapshotSymbolConsumers(store: CodeGraphStore, snapshotId: number): SymbolConsumers[] {\n return computeSymbolConsumers(snapshotReferenceEdges(store, snapshotId));\n}\n\n/** Co-import symbol coupling pairs for one snapshot. */\nexport function snapshotSymbolCoupling(\n store: CodeGraphStore,\n snapshotId: number,\n options: SymbolCouplingOptions = {},\n): SymbolCouplingPair[] {\n return computeSymbolCoupling(snapshotReferenceEdges(store, snapshotId), options);\n}\n","import {\n computeSymbolConsumers,\n computeSymbolCoupling,\n type ReferenceEdgeLite,\n} from \"./symbol-coupling.js\";\n\n/**\n * Dashboard payload assembly for symbol-level coupling (C-60). Turns the raw\n * `references` edge set into two lean, capped slices the Coupling view renders,\n * so a god-file like `types.ts` decomposes into *which symbol goes where*\n * instead of one aggregate file node:\n *\n * - **Slice B — `symbolCoupling`**: symbol pairs consistently co-imported by the\n * same files (structural, used-together coupling; drift-free).\n * - **Slice C — `symbolConsumers`**: per-file groups of exported symbols with\n * the files that consume each — the literal \"what IN this file is used where\".\n *\n * Kept out of dashboard-payload.ts (at its LOC ceiling) so that file stays lean.\n */\n\n/** One co-imported symbol pair, dashboard-lean (Slice B). */\nexport interface SymbolCouplingRow {\n aName: string;\n aFile: string;\n bName: string;\n bFile: string;\n coImports: number;\n crossFile: boolean;\n}\n\n/** One symbol and the files that consume it (Slice C). */\nexport interface SymbolConsumerRow {\n name: string;\n /** Up to CONSUMER_SAMPLE consuming file ids. */\n consumers: string[];\n /** Full distinct-consumer count (consumers may be truncated). */\n consumerCount: number;\n}\n\n/** A file's shared exports and where each goes (Slice C, grouped for the view). */\nexport interface SymbolConsumerGroup {\n fileId: string;\n symbols: SymbolConsumerRow[];\n /** Sum of consumer counts across kept symbols — the group's ordering weight. */\n totalConsumers: number;\n}\n\nexport interface SymbolCouplingPayload {\n symbolCoupling: SymbolCouplingRow[];\n symbolConsumers: SymbolConsumerGroup[];\n}\n\n/** A symbol must be imported by at least this many files to count as shared. */\nconst MIN_SHARED_CONSUMERS = 2;\nconst MAX_PAIRS = 40;\nconst MAX_GROUPS = 15;\nconst MAX_SYMBOLS_PER_GROUP = 10;\nconst CONSUMER_SAMPLE = 12;\n\nexport function buildSymbolCouplingPayload(\n edges: readonly ReferenceEdgeLite[],\n): SymbolCouplingPayload {\n return {\n symbolCoupling: buildCouplingRows(edges),\n symbolConsumers: buildConsumerGroups(edges),\n };\n}\n\nfunction buildCouplingRows(\n edges: readonly ReferenceEdgeLite[],\n): SymbolCouplingRow[] {\n return computeSymbolCoupling(edges)\n .slice(0, MAX_PAIRS)\n .map((p) => ({\n aName: p.aName,\n aFile: p.aFile,\n bName: p.bName,\n bFile: p.bFile,\n coImports: p.coImports,\n crossFile: p.crossFile,\n }));\n}\n\nfunction buildConsumerGroups(\n edges: readonly ReferenceEdgeLite[],\n): SymbolConsumerGroup[] {\n const byFile = new Map<string, SymbolConsumerRow[]>();\n for (const s of computeSymbolConsumers(edges)) {\n if (s.consumers.length < MIN_SHARED_CONSUMERS) continue;\n const bucket = byFile.get(s.fileId) ?? [];\n bucket.push({\n name: s.name,\n consumers: s.consumers.slice(0, CONSUMER_SAMPLE),\n consumerCount: s.consumers.length,\n });\n byFile.set(s.fileId, bucket);\n }\n return foldGroups(byFile);\n}\n\nfunction foldGroups(\n byFile: ReadonlyMap<string, SymbolConsumerRow[]>,\n): SymbolConsumerGroup[] {\n const groups: SymbolConsumerGroup[] = [];\n for (const [fileId, symbols] of byFile) {\n const kept = symbols.slice(0, MAX_SYMBOLS_PER_GROUP);\n groups.push({\n fileId,\n symbols: kept,\n totalConsumers: kept.reduce((n, s) => n + s.consumerCount, 0),\n });\n }\n return groups\n .sort(\n (a, b) =>\n b.symbols.length - a.symbols.length ||\n b.totalConsumers - a.totalConsumers ||\n (a.fileId < b.fileId ? -1 : 1),\n )\n .slice(0, MAX_GROUPS);\n}\n","import type { CodeGraphStore } from \"./store.js\";\nimport type { MetricAggregate } from \"./store-reads.js\";\nimport type { GraphEdge, GraphMetric, GraphNode } from \"./types.js\";\n\n/**\n * The free-function reading surface named in the package API. Each delegates to\n * the store's method of the same name, so a caller that only reads a snapshot\n * never has to hold on to the store's shape.\n */\nexport function listNodes(\n store: CodeGraphStore,\n snapshotId: number,\n opts?: { includeSymbols?: boolean },\n): GraphNode[] {\n return store.listNodes(snapshotId, opts);\n}\n\nexport function listEdges(\n store: CodeGraphStore,\n snapshotId: number,\n opts?: { includeReferences?: boolean },\n): GraphEdge[] {\n return store.listEdges(snapshotId, opts);\n}\n\nexport function listMetrics(store: CodeGraphStore, snapshotId: number): GraphMetric[] {\n return store.listMetrics(snapshotId);\n}\n\nexport function listMetricsForNode(store: CodeGraphStore, snapshotId: number, nodeId: string): GraphMetric[] {\n return store.listMetricsForNode(snapshotId, nodeId);\n}\n\nexport function listEdgesTouching(\n store: CodeGraphStore,\n snapshotId: number,\n nodeId: string,\n opts?: { includeReferences?: boolean },\n): GraphEdge[] {\n return store.listEdgesTouching(snapshotId, nodeId, opts);\n}\n\nexport function aggregateMetrics(\n store: CodeGraphStore,\n snapshotId: number,\n opts?: { name?: string },\n): MetricAggregate[] {\n return store.aggregateMetrics(snapshotId, opts);\n}\n","import type { NodeKind } from \"../types.js\";\nimport type { MetricDescriptor } from \"./types.js\";\n\nconst FILE: readonly NodeKind[] = [\"file\"];\nconst SYMBOL: readonly NodeKind[] = [\"symbol\"];\nconst STRUCTURAL: readonly NodeKind[] = [\"file\", \"module\", \"external\"];\n\n/** Degree metrics from `metrics.ts`, recomputed over the whole assembled graph on every index. */\nconst DEGREE: readonly MetricDescriptor[] = [\n {\n name: \"fan_in\", unit: \"count\", appliesTo: STRUCTURAL, rollup: \"none\", direction: \"neutral\",\n absent: \"zero\", source: \"degree\",\n description: \"Import and re-export edges into the node. Summing over a group would count its internal edges.\",\n },\n {\n name: \"fan_out\", unit: \"count\", appliesTo: STRUCTURAL, rollup: \"none\", direction: \"higher-worse\",\n absent: \"zero\", source: \"degree\",\n description: \"Import and re-export edges out of the node. Summing over a group would count its internal edges.\",\n },\n {\n name: \"instability\", unit: \"ratio\", appliesTo: STRUCTURAL, rollup: \"none\", direction: \"neutral\",\n absent: \"exclude\", source: \"degree\",\n description: \"fan_out / (fan_in + fan_out); written only when the node has an import edge.\",\n },\n {\n name: \"utilization\", unit: \"count\", appliesTo: [...STRUCTURAL, \"symbol\"], rollup: \"none\", direction: \"neutral\",\n absent: \"zero\", source: \"degree\",\n description: \"Inbound edges weighted by reference count over the barrel-resolved graph: how heavily a node is used.\",\n },\n];\n\n/** Pure functions of one file's bytes (`source-metrics.ts`, `lcom.ts`), carried forward under reuse. */\nconst SOURCE: readonly MetricDescriptor[] = [\n {\n name: \"loc\", unit: \"lines\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"source-metrics\", description: \"Non-blank lines in the file.\",\n },\n {\n name: \"function_count\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"neutral\",\n absent: \"zero\", source: \"source-metrics\", description: \"Functions, methods, and arrow functions declared in the file.\",\n },\n {\n name: \"cyclomatic_max\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\", description: \"Highest cyclomatic complexity of any function in the file; points attention at branchy code.\",\n },\n {\n name: \"cyclomatic_sum\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"source-metrics\", description: \"Cyclomatic complexity summed over the file's functions; points attention at branchy code.\",\n },\n {\n name: \"cognitive_max\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\", description: \"Highest cognitive complexity of any function in the file, an estimate of comprehension friction.\",\n },\n {\n name: \"cognitive_sum\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"source-metrics\", description: \"Cognitive complexity summed over the file's functions, an estimate of comprehension friction.\",\n },\n {\n name: \"max_nesting_depth\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\", description: \"Deepest block nesting inside any function in the file.\",\n },\n {\n name: \"jsx_depth_max\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Deepest JSX element tree in the file: the max of symbol_jsx_depth over its functions and module-scope JSX. Written only when > 0.\",\n },\n {\n name: \"symbol_cognitive\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Cognitive complexity (comprehension friction) of the function a symbol names; the max when several functions share the name.\",\n },\n {\n name: \"symbol_cyclomatic\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Cyclomatic complexity (an attention pointer) of the function a symbol names; the max when several functions share the name.\",\n },\n {\n name: \"symbol_loc\", unit: \"lines\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Lines spanned by the function a symbol names, signature included; the max when several share the name.\",\n },\n {\n name: \"symbol_max_nesting\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Deepest block nesting inside the function a symbol names; the max when several share the name.\",\n },\n {\n name: \"symbol_jsx_depth\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Most JSX elements on one ancestor chain in the function, fragments not counted. Walks into {…} and inline callbacks, stops at a nested named function; attribute JSX sits one below its owner. Written only when > 0.\",\n },\n {\n name: \"symbol_comment_lines\", unit: \"lines\", appliesTo: SYMBOL, rollup: \"max\", direction: \"neutral\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Rows holding a comment inside the function a symbol names, the docstring excluded; the max when several share the name.\",\n },\n {\n name: \"symbol_docstring_lines\", unit: \"lines\", appliesTo: SYMBOL, rollup: \"max\", direction: \"neutral\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Rows of the function's docstring: the Python docstring, or the JSDoc block attached to a TypeScript declaration.\",\n },\n {\n name: \"symbol_body_lines\", unit: \"lines\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Non-blank rows of the function's body that hold code, comments and the docstring excluded.\",\n },\n {\n name: \"symbol_comment_ratio\", unit: \"ratio\", appliesTo: SYMBOL, rollup: \"max\", direction: \"neutral\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"symbol_comment_lines / max(symbol_body_lines, 1). High values suggest narration; zero is not a defect.\",\n },\n {\n name: \"symbol_narrating_comments\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"Comments in the body whose words overlap the next statement's identifiers by 2 tokens or half the comment. A candidate signal.\",\n },\n {\n name: \"symbol_pass_through\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"source-metrics\",\n description: \"1 when the function's body is one call forwarding every parameter, in order, as a bare argument; else 0.\",\n },\n {\n name: \"symbol_caller_count\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"neutral\",\n absent: \"exclude\", source: \"call-graph\",\n description: \"Distinct symbols, or files at module level, with a resolved call to this function, method or class. Unresolved calls are not counted.\",\n },\n {\n name: \"symbol_single_caller_helper\", unit: \"count\", appliesTo: SYMBOL, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"call-graph\",\n description: \"1 when a non-exported symbol has exactly one resolved caller and that caller is a symbol; else 0.\",\n },\n {\n name: \"symbol_constant_params\", unit: \"count\", appliesTo: SYMBOL, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"call-graph\",\n description: \"Parameters that every one of at least 2 resolved call sites passes the same literal, or never passes. Rest and keyword-splat parameters are ignored.\",\n },\n {\n name: \"except_count\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"neutral\",\n absent: \"zero\", source: \"exception-handling\", description: \"Python except clauses and TypeScript catch clauses in the file.\",\n },\n {\n name: \"except_density\", unit: \"per100loc\", appliesTo: FILE, rollup: \"none\", direction: \"higher-worse\",\n absent: \"zero\", source: \"exception-handling\", description: \"except_count per 100 non-blank lines. Recompute from the sums for a group.\",\n },\n {\n name: \"swallowed_except\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"exception-handling\",\n description: \"Handlers whose body is empty, pass, ..., continue, a bare or empty return, or a single logging call. Exempts Python's `except ImportError`/`ModuleNotFoundError` (alone or paired), the standard optional-dependency idiom.\",\n },\n {\n name: \"class_count\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"neutral\",\n absent: \"zero\", source: \"lcom\", description: \"Classes declared in the file; written only when there is one.\",\n },\n {\n name: \"lcom4_max\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"lcom\", description: \"Highest LCOM4 of any class in the file; above 1 means the class could split.\",\n },\n];\n\n/** Sparse per-file smells: a row only when the count clears the writer's floor. */\nconst SMELLS: readonly MetricDescriptor[] = [\n {\n name: \"unreachable_statements\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"dead-code\", description: \"Statements after an unconditional return, throw, break, or continue. TypeScript only.\",\n },\n {\n name: \"unused_locals\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"dead-code\", description: \"Local bindings never read. TypeScript only.\",\n },\n {\n name: \"unused_params\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"dead-code\", description: \"Trailing parameters never read. TypeScript only.\",\n },\n {\n name: \"loop_depth\", unit: \"count\", appliesTo: FILE, rollup: \"max\", direction: \"higher-worse\",\n absent: \"zero\", source: \"growth-risk\", description: \"Deepest lexical loop nesting; written at 2 or more.\",\n },\n {\n name: \"recursive_functions\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"growth-risk\", description: \"Functions that call themselves by name. TypeScript only.\",\n },\n {\n name: \"search_in_loop\", unit: \"count\", appliesTo: FILE, rollup: \"sum\", direction: \"higher-worse\",\n absent: \"zero\", source: \"growth-risk\", description: \"Linear searches such as .includes or .find inside a loop. TypeScript only.\",\n },\n];\n\n/** Git-history metrics from `history-metrics.ts`; `{w}` is a window such as `30d` or `lifetime`. */\nconst HISTORY: readonly MetricDescriptor[] = [\n {\n name: \"churn_{w}\", unit: \"lines\", appliesTo: FILE, rollup: \"sum\", direction: \"neutral\",\n absent: \"zero\", source: \"history\", windowed: true, description: \"Lines added plus deleted in the {w} window.\",\n },\n {\n name: \"churn_{w}_commits\", unit: \"count\", appliesTo: FILE, rollup: \"none\", direction: \"neutral\",\n absent: \"zero\", source: \"history\", windowed: true,\n description: \"Commits touching the file in the {w} window. A group's distinct commits are not the sum.\",\n },\n {\n name: \"churn_{w}_authors\", unit: \"count\", appliesTo: FILE, rollup: \"none\", direction: \"neutral\",\n absent: \"zero\", source: \"history\", windowed: true,\n description: \"Distinct authors of the file's commits in the {w} window. Not additive.\",\n },\n {\n name: \"recency_{w}\", unit: \"ratio\", appliesTo: FILE, rollup: \"none\", direction: \"neutral\",\n absent: \"exclude\", source: \"history\", windowed: true,\n description: \"min(1, file age / window) for a file that churned in the {w} window; 1 for lifetime. Discounts the hotspot score, churn × complexity after Adam Tornhill and CodeScene.\",\n },\n {\n name: \"file_age_days\", unit: \"days\", appliesTo: FILE, rollup: \"max\", direction: \"neutral\",\n absent: \"exclude\", source: \"history\", description: \"Days since the file first appeared in git history.\",\n },\n {\n name: \"bus_factor_{w}\", unit: \"count\", appliesTo: FILE, rollup: \"none\", direction: \"lower-worse\",\n absent: \"exclude\", source: \"history\", windowed: true,\n description: \"Fewest authors covering half the file's churn in the {w} window.\",\n },\n {\n name: \"top_author_share_{w}\", unit: \"ratio\", appliesTo: FILE, rollup: \"none\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"history\", windowed: true,\n description: \"Share of the file's churn in the {w} window written by its top author.\",\n },\n];\n\n/** Test linking (`test-linker.ts`) and the Istanbul overlay (`coverage.ts`), keyed on source nodes. */\nconst TESTS: readonly MetricDescriptor[] = [\n {\n name: \"linked_test_count\", unit: \"count\", appliesTo: FILE, rollup: \"none\", direction: \"lower-worse\",\n absent: \"zero\", source: \"test-linker\",\n description: \"Test files linked to this source. One test can link to several sources, so it does not sum.\",\n },\n {\n name: \"test_bus_factor_{w}\", unit: \"count\", appliesTo: FILE, rollup: \"none\", direction: \"lower-worse\",\n absent: \"exclude\", source: \"test-linker\", windowed: true,\n description: \"Bus factor of the churn on this source's linked tests in the {w} window.\",\n },\n {\n name: \"test_top_author_share_{w}\", unit: \"ratio\", appliesTo: FILE, rollup: \"none\", direction: \"higher-worse\",\n absent: \"exclude\", source: \"test-linker\", windowed: true,\n description: \"Top author's share of the churn on this source's linked tests in the {w} window.\",\n },\n {\n name: \"coverage_pct\", unit: \"percent\", appliesTo: [\"file\", \"symbol\"], rollup: \"none\", direction: \"lower-worse\",\n absent: \"exclude\", source: \"coverage\",\n description: \"Functions covered over functions total, from an ingested Istanbul report. Never written by the indexer.\",\n },\n];\n\n/** Every metric name code-graph writes, with windowed names as `{w}` templates. */\nexport const METRIC_CATALOGUE: readonly MetricDescriptor[] = [...DEGREE, ...SOURCE, ...SMELLS, ...HISTORY, ...TESTS];\n","import { METRIC_CATALOGUE } from \"./entries.js\";\nimport type { MetricDescriptor } from \"./types.js\";\n\nconst WINDOW_TOKEN = \"{w}\";\n/** Mirrors `windowSuffix` in history-recency.ts, which this module cannot import and stay free of Node. */\nconst WINDOW_PATTERN = \"(\\\\d+d|lifetime)\";\n\ninterface WindowedMatcher {\n pattern: RegExp;\n template: MetricDescriptor;\n}\n\nconst BY_NAME = new Map(METRIC_CATALOGUE.filter((d) => !d.windowed).map((d) => [d.name, d]));\n\nconst WINDOWED: readonly WindowedMatcher[] = METRIC_CATALOGUE.filter((d) => d.windowed).map((template) => ({\n pattern: new RegExp(`^${template.name.replace(WINDOW_TOKEN, WINDOW_PATTERN)}$`),\n template,\n}));\n\nfunction resolveWindow(template: MetricDescriptor, window: string): MetricDescriptor {\n const resolved: MetricDescriptor = {\n ...template,\n name: template.name.replace(WINDOW_TOKEN, window),\n description: template.description.replace(WINDOW_TOKEN, window),\n window,\n };\n delete resolved.windowed;\n return resolved;\n}\n\n/** The descriptor for a stored metric name, resolving windowed names such as `churn_90d`; null when uncatalogued. */\nexport function describeMetric(name: string): MetricDescriptor | null {\n const exact = BY_NAME.get(name);\n if (exact) return exact;\n for (const { pattern, template } of WINDOWED) {\n const match = pattern.exec(name);\n if (match) return resolveWindow(template, match[1]!);\n }\n return null;\n}\n\n/** Descriptors for a set of stored names, in the order given; uncatalogued names are returned separately. */\nexport function describeMetrics(names: Iterable<string>): { described: MetricDescriptor[]; unknown: string[] } {\n const described: MetricDescriptor[] = [];\n const unknown: string[] = [];\n for (const name of new Set(names)) {\n const descriptor = describeMetric(name);\n if (descriptor) described.push(descriptor);\n else unknown.push(name);\n }\n return { described, unknown };\n}\n","import type { CodeGraphStore } from \"../store.js\";\nimport type { GraphEdge, GraphMetric, GraphNode } from \"../types.js\";\n\n/** The three whole-snapshot reads rule evaluation needs; any store with them can be checked. */\nexport type RuleStore = Pick<CodeGraphStore, \"listNodes\" | \"listEdges\" | \"listMetrics\">;\n\nexport interface RuleContext {\n nodes: readonly GraphNode[];\n /** Kept apart from `nodes` so only rules that ask for `kind: \"symbol\"` evaluate them. */\n symbolNodes: readonly GraphNode[];\n nodesById: Map<string, GraphNode>;\n metricsByNode: Map<string, Map<string, number>>;\n edges: readonly GraphEdge[];\n}\n\n/** The snapshot's file-level graph (no references edges), its symbol layer, and its non-null metrics. */\nexport function buildRuleContext(store: RuleStore, snapshotId: number): RuleContext {\n const all = store.listNodes(snapshotId, { includeSymbols: true });\n const nodes = all.filter((n) => n.kind !== \"symbol\");\n const symbolNodes = all.filter((n) => n.kind === \"symbol\");\n const edges = store.listEdges(snapshotId);\n const nodesById = new Map<string, GraphNode>();\n for (const n of nodes) nodesById.set(n.id, n);\n return { nodes, symbolNodes, nodesById, metricsByNode: indexMetrics(store.listMetrics(snapshotId)), edges };\n}\n\nfunction indexMetrics(metrics: readonly GraphMetric[]): Map<string, Map<string, number>> {\n const metricsByNode = new Map<string, Map<string, number>>();\n for (const m of metrics) {\n if (m.value === null) continue;\n let inner = metricsByNode.get(m.nodeId);\n if (!inner) {\n inner = new Map();\n metricsByNode.set(m.nodeId, inner);\n }\n inner.set(m.name, m.value);\n }\n return metricsByNode;\n}\n","import type { GraphEdge } from \"../types.js\";\nimport type { CheckRule, Severity } from \"./types.js\";\n\nexport function severityOf(rule: CheckRule): Severity {\n return rule.severity ?? \"error\";\n}\n\nexport function formatNumber(n: number): string {\n if (Number.isInteger(n)) return String(n);\n return n.toFixed(3).replace(/\\.?0+$/, \"\");\n}\n\nexport function isImportEdge(edge: GraphEdge): boolean {\n return edge.kind === \"imports\" || edge.kind === \"re-exports\";\n}\n\n/** Maps an id to the longest prefix it sits under, so a nested package wins over its parent. */\nexport function longestPrefixMatcher(prefixes: readonly string[]): (id: string) => string | null {\n const byLength = [...prefixes].sort((a, b) => b.length - a.length);\n return (id) => {\n for (const p of byLength) {\n if (id === p || id.startsWith(`${p}/`)) return p;\n }\n return null;\n };\n}\n","import type { GraphEdge } from \"../types.js\";\nimport type { RuleContext } from \"./context.js\";\nimport { compilePatterns, matchesAny } from \"./patterns.js\";\nimport { isImportEdge, longestPrefixMatcher, severityOf } from \"./rule-helpers.js\";\nimport type {\n CheckViolation,\n ForbidImportRule,\n LayeredDepsRule,\n NoInternalOnlyBarrelsRule,\n} from \"./types.js\";\n\nfunction layerIndex(layers: readonly string[][]): Map<string, number> {\n const packageLayer = new Map<string, number>();\n for (let i = 0; i < layers.length; i++) {\n for (const pkg of layers[i]!) packageLayer.set(pkg, i);\n }\n return packageLayer;\n}\n\n/** Layer strings are path prefixes such as `packages/cli`; an edge may only point to its own layer or a lower one. */\nexport function runLayeredDepsRule(rule: LayeredDepsRule, ctx: RuleContext): CheckViolation[] {\n const packageLayer = layerIndex(rule.layers);\n const packageOf = longestPrefixMatcher([...packageLayer.keys()]);\n const excludedRoles = new Set(rule.excludeRoles ?? []);\n const hasExcludedRole = (id: string): boolean => {\n const role = ctx.nodesById.get(id)?.role;\n return role !== undefined && excludedRoles.has(role);\n };\n const out: CheckViolation[] = [];\n for (const edge of ctx.edges) {\n if (!isImportEdge(edge)) continue;\n if (hasExcludedRole(edge.srcId) || hasExcludedRole(edge.dstId)) continue;\n const srcPkg = packageOf(edge.srcId);\n const dstPkg = packageOf(edge.dstId);\n if (srcPkg === null || dstPkg === null) continue;\n const srcLayer = packageLayer.get(srcPkg)!;\n const dstLayer = packageLayer.get(dstPkg)!;\n if (srcLayer >= dstLayer) continue;\n out.push({\n ruleId: rule.id,\n severity: severityOf(rule),\n nodeId: edge.srcId,\n destinationId: edge.dstId,\n message: `${edge.srcId} (${srcPkg}, layer ${srcLayer}) imports ${edge.dstId} (${dstPkg}, layer ${dstLayer})`,\n });\n }\n return out;\n}\n\nexport function runForbidImportRule(rule: ForbidImportRule, ctx: RuleContext): CheckViolation[] {\n const fromRx = compilePatterns([rule.from]);\n const toRx = compilePatterns([rule.to]);\n const exceptRx = compilePatterns(rule.except);\n const out: CheckViolation[] = [];\n for (const edge of ctx.edges) {\n if (!isImportEdge(edge)) continue;\n if (!matchesAny(edge.srcId, fromRx)) continue;\n if (!matchesAny(edge.dstId, toRx) || matchesAny(edge.dstId, exceptRx)) continue;\n out.push({\n ruleId: rule.id,\n severity: severityOf(rule),\n nodeId: edge.srcId,\n destinationId: edge.dstId,\n message: `${edge.srcId} imports ${edge.dstId} (forbidden: ${rule.from} → ${rule.to})`,\n });\n }\n return out;\n}\n\nfunction importersByDestination(edges: readonly GraphEdge[]): Map<string, string[]> {\n const importersByDst = new Map<string, string[]>();\n for (const edge of edges) {\n if (!isImportEdge(edge)) continue;\n let list = importersByDst.get(edge.dstId);\n if (!list) {\n list = [];\n importersByDst.set(edge.dstId, list);\n }\n list.push(edge.srcId);\n }\n return importersByDst;\n}\n\nexport function runNoInternalOnlyBarrelsRule(\n rule: NoInternalOnlyBarrelsRule,\n ctx: RuleContext,\n): CheckViolation[] {\n const packageOf = longestPrefixMatcher(rule.packageRoots);\n const excluders = compilePatterns(rule.exclude);\n const importersByDst = importersByDestination(ctx.edges);\n const out: CheckViolation[] = [];\n for (const node of ctx.nodes) {\n if (node.kind !== \"file\") continue;\n if (node.role !== \"barrel\") continue;\n if (matchesAny(node.id, excluders)) continue;\n const barrelPkg = packageOf(node.id);\n if (barrelPkg === null) continue;\n const importers = importersByDst.get(node.id) ?? [];\n const externalCount = importers.reduce((n, src) => (packageOf(src) !== barrelPkg ? n + 1 : n), 0);\n if (externalCount > 0) continue;\n out.push({\n ruleId: rule.id,\n severity: severityOf(rule),\n nodeId: node.id,\n message: barrelMessage(barrelPkg, importers.length),\n });\n }\n return out;\n}\n\nfunction barrelMessage(barrelPkg: string, importerCount: number): string {\n return importerCount === 0\n ? `barrel in package \"${barrelPkg}\" has no importers`\n : `barrel in package \"${barrelPkg}\" has ${importerCount} internal importer(s) but zero external`;\n}\n","import type { GraphNode } from \"../types.js\";\nimport type { CheckViolation } from \"./types.js\";\n\nexport const CODE_GRAPH_TOOL = \"code-graph\";\n\nexport type ViolationLocation = Pick<CheckViolation, \"path\" | \"lineStart\" | \"lineEnd\" | \"symbol\">;\n\n/** Where a node lives in the source: a symbol points at its parent file and its own line span. */\nexport function locateNode(node: GraphNode): ViolationLocation {\n if (node.kind !== \"symbol\") return { path: node.id };\n const location: ViolationLocation = { path: node.parentId ?? node.id, symbol: node.name };\n const startLine = node.attrs?.startLine;\n const endLine = node.attrs?.endLine;\n if (typeof startLine === \"number\") location.lineStart = startLine;\n if (typeof endLine === \"number\") location.lineEnd = endLine;\n return location;\n}\n","import type { GraphNode } from \"../types.js\";\nimport type { RuleContext } from \"./context.js\";\nimport { formatNumber, severityOf } from \"./rule-helpers.js\";\nimport type { CheckViolation, MetricOutlierRule } from \"./types.js\";\nimport { CODE_GRAPH_TOOL, locateNode } from \"./violation-location.js\";\n\nexport const DEFAULT_OUTLIER_MIN_SAMPLE = 20;\n\n/**\n * A threshold drawn from the snapshot itself rather than fixed in the rule, so\n * one rule reads the same across repositories of different house styles. Below\n * `minSample` carriers the percentile means little, so the rule stays silent.\n */\nexport function runMetricOutlierRule(rule: MetricOutlierRule, ctx: RuleContext): CheckViolation[] {\n const pool = rule.kind === \"symbol\" ? ctx.symbolNodes : ctx.nodes;\n const carriers: { node: GraphNode; value: number }[] = [];\n for (const node of pool) {\n if (node.kind !== rule.kind) continue;\n const value = ctx.metricsByNode.get(node.id)?.get(rule.metric);\n if (value !== undefined) carriers.push({ node, value });\n }\n const ranked = rule.rankNonZero ? carriers.filter((c) => c.value > 0) : carriers;\n if (ranked.length < (rule.minSample ?? DEFAULT_OUTLIER_MIN_SAMPLE)) return [];\n const threshold = percentileOf(ranked.map((c) => c.value), rule.percentile);\n return ranked\n .filter((c) => c.value > threshold && (rule.floor === undefined || c.value > rule.floor))\n .map((c) => toViolation(rule, c.node, c.value, threshold));\n}\n\n/** Linear interpolation between closest ranks, the definition numpy and spreadsheets use by default. */\nexport function percentileOf(values: readonly number[], percentile: number): number {\n const sorted = [...values].sort((a, b) => a - b);\n const rank = (percentile / 100) * (sorted.length - 1);\n const lower = Math.floor(rank);\n const upper = Math.min(lower + 1, sorted.length - 1);\n return sorted[lower]! + (sorted[upper]! - sorted[lower]!) * (rank - lower);\n}\n\nfunction toViolation(rule: MetricOutlierRule, node: GraphNode, value: number, threshold: number): CheckViolation {\n const floorSuffix = rule.floor === undefined ? \"\" : `, floor ${formatNumber(rule.floor)}`;\n const bound = `p${formatNumber(rule.percentile)} ${formatNumber(threshold)}${floorSuffix}`;\n return {\n ruleId: rule.id,\n severity: severityOf(rule),\n nodeId: node.id,\n metric: rule.metric,\n value,\n threshold,\n message: `${rule.metric}=${formatNumber(value)} > ${bound}`,\n ...locateNode(node),\n evidence: `${rule.metric}=${formatNumber(value)} (${bound})`,\n tool: CODE_GRAPH_TOOL,\n };\n}\n","import type { GraphNode, NodeKind, NodeRole } from \"../types.js\";\nimport type { RuleContext } from \"./context.js\";\nimport { compilePatterns, matchesAny } from \"./patterns.js\";\nimport { formatNumber, severityOf } from \"./rule-helpers.js\";\nimport type {\n CheckViolation,\n MetricMaxRule,\n MetricMinRule,\n MetricProductMaxRule,\n} from \"./types.js\";\nimport { CODE_GRAPH_TOOL, locateNode } from \"./violation-location.js\";\n\ntype MetricRule = MetricMaxRule | MetricMinRule | MetricProductMaxRule;\n\ninterface NodeFilter {\n kind?: NodeKind;\n excluders: RegExp[];\n excludedRoles: Set<NodeRole>;\n}\n\nfunction nodeFilter(rule: MetricRule): NodeFilter {\n return {\n kind: rule.kind,\n excluders: compilePatterns(rule.exclude),\n excludedRoles: new Set(rule.excludeRoles ?? []),\n };\n}\n\nfunction passesFilter(node: GraphNode, filter: NodeFilter): boolean {\n if (filter.kind && node.kind !== filter.kind) return false;\n if (matchesAny(node.id, filter.excluders)) return false;\n if (node.role && filter.excludedRoles.has(node.role)) return false;\n return true;\n}\n\n/** Symbol nodes only when the rule asks for them, so file rules and their baselines stay as they were. */\nfunction candidateNodes(rule: MetricRule, ctx: RuleContext): GraphNode[] {\n const filter = nodeFilter(rule);\n const pool = rule.kind === \"symbol\" ? ctx.symbolNodes : ctx.nodes;\n return pool.filter((node) => passesFilter(node, filter));\n}\n\ninterface Breach {\n node: GraphNode;\n metric: string;\n value: number;\n threshold: number;\n message: string;\n evidence: string;\n}\n\nfunction toViolation(rule: MetricRule, breach: Breach): CheckViolation {\n return {\n ruleId: rule.id,\n severity: severityOf(rule),\n nodeId: breach.node.id,\n metric: breach.metric,\n value: breach.value,\n threshold: breach.threshold,\n message: breach.message,\n ...locateNode(breach.node),\n evidence: breach.evidence,\n tool: CODE_GRAPH_TOOL,\n };\n}\n\nfunction thresholdBreach(node: GraphNode, metric: string, value: number, bound: \"max\" | \"min\", threshold: number): Breach {\n const op = bound === \"max\" ? \">\" : \"<\";\n return {\n node,\n metric,\n value,\n threshold,\n message: `${metric}=${formatNumber(value)} ${op} ${formatNumber(threshold)}`,\n evidence: `${metric}=${formatNumber(value)} (${bound} ${formatNumber(threshold)})`,\n };\n}\n\nexport function runMetricMaxRule(rule: MetricMaxRule, ctx: RuleContext): CheckViolation[] {\n const out: CheckViolation[] = [];\n for (const node of candidateNodes(rule, ctx)) {\n const value = ctx.metricsByNode.get(node.id)?.get(rule.metric);\n if (value === undefined || value <= rule.max) continue;\n out.push(toViolation(rule, thresholdBreach(node, rule.metric, value, \"max\", rule.max)));\n }\n return out;\n}\n\nexport function runMetricMinRule(rule: MetricMinRule, ctx: RuleContext): CheckViolation[] {\n const out: CheckViolation[] = [];\n for (const node of candidateNodes(rule, ctx)) {\n const value = ctx.metricsByNode.get(node.id)?.get(rule.metric);\n if (value === undefined || value >= rule.min) continue;\n out.push(toViolation(rule, thresholdBreach(node, rule.metric, value, \"min\", rule.min)));\n }\n return out;\n}\n\nexport function runMetricProductMaxRule(rule: MetricProductMaxRule, ctx: RuleContext): CheckViolation[] {\n const out: CheckViolation[] = [];\n for (const node of candidateNodes(rule, ctx)) {\n const inner = ctx.metricsByNode.get(node.id);\n if (!inner) continue;\n const components = collectComponents(rule.metrics, inner);\n if (!components) continue;\n const product = components.reduce((a, b) => a * b, 1);\n if (product <= rule.max) continue;\n out.push(toViolation(rule, productBreach(rule, node, components, product)));\n }\n return out;\n}\n\nfunction productBreach(\n rule: MetricProductMaxRule,\n node: GraphNode,\n components: readonly number[],\n product: number,\n): Breach {\n const detail = rule.metrics.map((m, i) => `${m}=${formatNumber(components[i]!)}`).join(\" * \");\n return {\n node,\n metric: rule.metrics.join(\" * \"),\n value: product,\n threshold: rule.max,\n message: `${detail} = ${formatNumber(product)} > ${formatNumber(rule.max)}`,\n evidence: `${detail} = ${formatNumber(product)} (max ${formatNumber(rule.max)})`,\n };\n}\n\nfunction collectComponents(\n metrics: readonly string[],\n values: ReadonlyMap<string, number>,\n): number[] | null {\n const out: number[] = [];\n for (const m of metrics) {\n const v = values.get(m);\n if (v === undefined) return null;\n out.push(v);\n }\n return out;\n}\n","import type { RuleContext } from \"./context.js\";\nimport { runForbidImportRule, runLayeredDepsRule, runNoInternalOnlyBarrelsRule } from \"./import-rules.js\";\nimport { runMetricOutlierRule } from \"./outlier-rule.js\";\nimport { runMetricMaxRule, runMetricMinRule, runMetricProductMaxRule } from \"./metric-rules.js\";\nimport type { CheckRule, CheckViolation } from \"./types.js\";\n\nexport function runRule(rule: CheckRule, ctx: RuleContext): CheckViolation[] {\n switch (rule.type) {\n case \"metric-max\":\n return runMetricMaxRule(rule, ctx);\n case \"metric-min\":\n return runMetricMinRule(rule, ctx);\n case \"metric-product-max\":\n return runMetricProductMaxRule(rule, ctx);\n case \"metric-outlier\":\n return runMetricOutlierRule(rule, ctx);\n case \"forbid-import\":\n return runForbidImportRule(rule, ctx);\n case \"layered-deps\":\n return runLayeredDepsRule(rule, ctx);\n case \"no-internal-only-barrels\":\n return runNoInternalOnlyBarrelsRule(rule, ctx);\n }\n}\n","import { aliasChain } from \"../identity/store-identity.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { buildRuleContext, type RuleStore } from \"./context.js\";\nimport { runRule } from \"./rules.js\";\nimport type { CheckResult, CheckRule, CheckViolation } from \"./types.js\";\nimport { rebasedViolationKey, violationKey } from \"./violation-key.js\";\n\nexport { rebasedViolationKey, violationKey } from \"./violation-key.js\";\n\nexport interface RunChecksOptions {\n snapshotId: number;\n rules: readonly CheckRule[];\n baselineSnapshotId?: number;\n}\n\nexport function runChecks(store: CodeGraphStore, options: RunChecksOptions): CheckResult {\n const ctx = buildRuleContext(store, options.snapshotId);\n const violations: CheckViolation[] = [];\n for (const rule of options.rules) {\n violations.push(...runRule(rule, ctx));\n }\n if (options.baselineSnapshotId) {\n const baselineKeys = collectBaselineKeys(store, options.baselineSnapshotId, options.snapshotId, options.rules);\n for (const v of violations) {\n if (baselineKeys.has(violationKey(v))) v.isCarryover = true;\n }\n }\n const counts = countByOriginAndSeverity(violations);\n return {\n snapshotId: options.snapshotId,\n baselineSnapshotId: options.baselineSnapshotId,\n rulesEvaluated: options.rules.length,\n nodesEvaluated: ctx.nodes.length,\n violations,\n ...counts,\n passed: counts.newErrors === 0,\n };\n}\n\n/** Every rule's violations in one snapshot with no baseline; needs only the three whole-snapshot reads. */\nexport function snapshotViolations(store: RuleStore, snapshotId: number, rules: readonly CheckRule[]): CheckViolation[] {\n const ctx = buildRuleContext(store, snapshotId);\n return rules.flatMap((rule) => runRule(rule, ctx));\n}\n\n/** Baseline violation keys in the checked snapshot's id space, so a moved file's violations carry over. */\nfunction collectBaselineKeys(\n store: CodeGraphStore,\n baselineSnapshotId: number,\n snapshotId: number,\n rules: readonly CheckRule[],\n): Set<string> {\n const ctx = buildRuleContext(store, baselineSnapshotId);\n const chain = aliasChain(store, baselineSnapshotId, snapshotId);\n const keys = new Set<string>();\n for (const rule of rules) {\n for (const v of runRule(rule, ctx)) keys.add(rebasedViolationKey(v, chain.resolve));\n }\n return keys;\n}\n\ninterface Counts {\n newErrors: number;\n newWarnings: number;\n carryoverErrors: number;\n carryoverWarnings: number;\n}\n\nfunction countByOriginAndSeverity(violations: readonly CheckViolation[]): Counts {\n const counts: Counts = { newErrors: 0, newWarnings: 0, carryoverErrors: 0, carryoverWarnings: 0 };\n for (const v of violations) {\n const isError = v.severity === \"error\";\n if (v.isCarryover) {\n if (isError) counts.carryoverErrors++;\n else counts.carryoverWarnings++;\n } else {\n if (isError) counts.newErrors++;\n else counts.newWarnings++;\n }\n }\n return counts;\n}\n","import type { CheckResult, CheckViolation, Severity } from \"./types.js\";\nimport { CODE_GRAPH_TOOL } from \"./violation-location.js\";\n\n/** One tool-neutral audit finding; every finding cites a path so a citation checker can verify it. */\nexport interface Finding {\n id: string;\n path: string;\n lineStart?: number;\n lineEnd?: number;\n symbol?: string;\n signal: string;\n value?: number;\n baseline?: number;\n threshold?: number;\n severity: Severity;\n evidence?: string;\n tool: string;\n}\n\n/** A diagnostic from an outside linter, shaped structurally so no linter package is imported. */\nexport interface ExternalDiagnostic {\n tool: string;\n rule: string;\n file: string;\n line: number;\n endLine?: number;\n message: string;\n severity: \"error\" | \"warning\";\n}\n\nexport function toFindings(result: CheckResult): Finding[] {\n return result.violations.map(violationToFinding);\n}\n\n/** Ids key on node id, not line, so a finding keeps its id when code above it moves. */\nfunction violationToFinding(v: CheckViolation): Finding {\n const tool = v.tool ?? CODE_GRAPH_TOOL;\n const target = v.destinationId ? `${v.nodeId}->${v.destinationId}` : v.nodeId;\n return withoutUndefined({\n id: `${tool}:${v.ruleId}:${target}`,\n path: v.path ?? v.nodeId,\n lineStart: v.lineStart,\n lineEnd: v.lineEnd,\n symbol: v.symbol,\n signal: v.ruleId,\n value: v.value,\n threshold: v.threshold,\n severity: v.severity,\n evidence: v.evidence ?? v.message,\n tool,\n });\n}\n\nexport function externalToFinding(input: ExternalDiagnostic): Finding {\n return withoutUndefined({\n id: `${input.tool}:${input.rule}:${input.file}:${input.line}`,\n path: input.file,\n lineStart: input.line,\n lineEnd: input.endLine,\n signal: input.rule,\n severity: input.severity,\n evidence: input.message,\n tool: input.tool,\n });\n}\n\nfunction withoutUndefined(finding: Finding): Finding {\n return Object.fromEntries(Object.entries(finding).filter(([, v]) => v !== undefined)) as Finding;\n}\n","import { createHash } from \"node:crypto\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { Finding } from \"./findings.js\";\n\nexport type VerdictLabel = \"confirmed\" | \"justified\" | \"unclear\";\n\nexport interface VerdictCitation {\n path: string;\n lineStart: number;\n lineEnd: number;\n quote: string;\n}\n\n/** A finding as stored against a snapshot, addressed by its `findingKey`. */\nexport interface StoredFinding {\n key: string;\n finding: Finding;\n /** Hash of the excerpt a reader would be shown for this finding; carry-forward compares it. */\n excerptHash?: string;\n}\n\n/** A model's judgement of one stored finding, after its citations were verified. */\nexport interface StoredVerdict {\n key: string;\n verdict: VerdictLabel;\n rationale: string;\n citations: VerdictCitation[];\n /** Hash of the excerpt the verdict judged. */\n excerptHash: string;\n model?: string;\n costUsd?: number;\n runId?: string;\n provenance?: string;\n controlRun?: \"ok\" | \"provisional\";\n dropped?: string[];\n /** The snapshot this verdict was carried from, when carry-forward copied it. */\n carriedFrom?: number;\n}\n\nexport interface FindingKeyInput {\n finding: Finding;\n /** The innermost symbol node id containing the finding; the finding's path when absent. */\n anchor?: string;\n /** The source text of the flagged lines. */\n flaggedText: string;\n excerptHash?: string;\n}\n\n/** Whitespace-insensitive, so reindenting or reflowing the flagged lines keeps the key. */\nexport function normalizeFlaggedText(text: string): string {\n return text\n .split(/\\r?\\n/)\n .map((line) => line.trim().replace(/\\s+/g, \" \"))\n .filter((line) => line.length > 0)\n .join(\"\\n\");\n}\n\nexport function hashText(text: string): string {\n return createHash(\"sha256\").update(text, \"utf8\").digest(\"hex\").slice(0, 16);\n}\n\n/**\n * A finding's identity across snapshots: no line number, so an inserted line above it\n * keeps the key, and a collision ordinal separates same-rule findings on the same text.\n */\nexport function findingKey(input: FindingKeyInput, ordinal = 0): string {\n const { finding } = input;\n const anchor = input.anchor ?? finding.path;\n const textHash = hashText(normalizeFlaggedText(input.flaggedText));\n return `${finding.tool}:${finding.signal}:${anchor}:${textHash}#${ordinal}`;\n}\n\n/** Key a whole audit's findings, numbering collisions in source order so the result ignores input order. */\nexport function keyFindings(inputs: readonly FindingKeyInput[]): StoredFinding[] {\n const ordered = [...inputs].sort(compareBySource);\n const seen = new Map<string, number>();\n return ordered.map((input) => {\n const base = findingKey(input);\n const ordinal = seen.get(base) ?? 0;\n seen.set(base, ordinal + 1);\n const stored: StoredFinding = { key: findingKey(input, ordinal), finding: input.finding };\n if (input.excerptHash !== undefined) stored.excerptHash = input.excerptHash;\n return stored;\n });\n}\n\nfunction compareBySource(a: FindingKeyInput, b: FindingKeyInput): number {\n const fa = a.finding;\n const fb = b.finding;\n return (\n fa.path.localeCompare(fb.path) ||\n (fa.lineStart ?? 0) - (fb.lineStart ?? 0) ||\n (fa.lineEnd ?? 0) - (fb.lineEnd ?? 0) ||\n (fa.evidence ?? \"\").localeCompare(fb.evidence ?? \"\") ||\n fa.id.localeCompare(fb.id)\n );\n}\n\ninterface FindingDbRow {\n key: string;\n excerpt_hash: string | null;\n attrs: string;\n}\n\ninterface VerdictDbRow {\n key: string;\n verdict: VerdictLabel;\n rationale: string;\n excerpt_hash: string;\n model: string | null;\n run_id: string | null;\n cost_usd: number | null;\n provenance: string | null;\n control_run: \"ok\" | \"provisional\" | null;\n carried_from: number | null;\n attrs: string;\n}\n\n/** Insert or replace findings by key within one snapshot. */\nexport function saveFindings(store: CodeGraphStore, snapshotId: number, findings: readonly StoredFinding[]): void {\n const insert = store.db.prepare(\n `INSERT OR REPLACE INTO finding\n (snapshot_id, key, finding_id, tool, signal, path, line_start, line_end, severity, excerpt_hash, attrs)\n VALUES (@snapshotId, @key, @findingId, @tool, @signal, @path, @lineStart, @lineEnd, @severity, @excerptHash, @attrs)`,\n );\n store.db.transaction(() => {\n for (const { key, finding, excerptHash } of findings) {\n insert.run({\n snapshotId,\n key,\n findingId: finding.id,\n tool: finding.tool,\n signal: finding.signal,\n path: finding.path,\n lineStart: finding.lineStart ?? null,\n lineEnd: finding.lineEnd ?? null,\n severity: finding.severity,\n excerptHash: excerptHash ?? null,\n attrs: JSON.stringify(finding),\n });\n }\n })();\n}\n\nexport function listFindings(store: CodeGraphStore, snapshotId: number): StoredFinding[] {\n const rows = store.db\n .prepare(\"SELECT key, excerpt_hash, attrs FROM finding WHERE snapshot_id = ? ORDER BY key\")\n .all(snapshotId) as FindingDbRow[];\n return rows.map((row) => {\n const stored: StoredFinding = { key: row.key, finding: JSON.parse(row.attrs) as Finding };\n if (row.excerpt_hash !== null) stored.excerptHash = row.excerpt_hash;\n return stored;\n });\n}\n\n/** Insert or replace verdicts by key within one snapshot. */\nexport function saveVerdicts(store: CodeGraphStore, snapshotId: number, verdicts: readonly StoredVerdict[]): void {\n const insert = store.db.prepare(\n `INSERT OR REPLACE INTO verdict\n (snapshot_id, key, verdict, rationale, excerpt_hash, model, run_id, cost_usd, provenance, control_run,\n carried_from, attrs)\n VALUES (@snapshotId, @key, @verdict, @rationale, @excerptHash, @model, @runId, @costUsd, @provenance,\n @controlRun, @carriedFrom, @attrs)`,\n );\n store.db.transaction(() => {\n for (const v of verdicts) insert.run(verdictParams(snapshotId, v));\n })();\n}\n\nfunction verdictParams(snapshotId: number, v: StoredVerdict): Record<string, unknown> {\n return {\n snapshotId,\n key: v.key,\n verdict: v.verdict,\n rationale: v.rationale,\n excerptHash: v.excerptHash,\n model: v.model ?? null,\n runId: v.runId ?? null,\n costUsd: v.costUsd ?? null,\n provenance: v.provenance ?? null,\n controlRun: v.controlRun ?? null,\n carriedFrom: v.carriedFrom ?? null,\n attrs: JSON.stringify({ citations: v.citations, dropped: v.dropped ?? [] }),\n };\n}\n\nexport function listVerdicts(store: CodeGraphStore, snapshotId: number): StoredVerdict[] {\n const rows = store.db\n .prepare(\"SELECT * FROM verdict WHERE snapshot_id = ? ORDER BY key\")\n .all(snapshotId) as VerdictDbRow[];\n return rows.map(rowToVerdict);\n}\n\nfunction rowToVerdict(row: VerdictDbRow): StoredVerdict {\n const attrs = JSON.parse(row.attrs) as { citations: VerdictCitation[]; dropped: string[] };\n const verdict: StoredVerdict = {\n key: row.key,\n verdict: row.verdict,\n rationale: row.rationale,\n citations: attrs.citations,\n excerptHash: row.excerpt_hash,\n };\n if (row.model !== null) verdict.model = row.model;\n if (row.cost_usd !== null) verdict.costUsd = row.cost_usd;\n if (row.run_id !== null) verdict.runId = row.run_id;\n if (row.provenance !== null) verdict.provenance = row.provenance;\n if (row.control_run !== null) verdict.controlRun = row.control_run;\n if (attrs.dropped.length > 0) verdict.dropped = attrs.dropped;\n if (row.carried_from !== null) verdict.carriedFrom = row.carried_from;\n return verdict;\n}\n\n/**\n * Copy each verdict of `from` onto the finding in `to` with the same key whose excerpt hash\n * equals the one the verdict judged. A verdict `to` already holds is kept. Returns the count copied.\n */\nexport function carryForwardVerdicts(store: CodeGraphStore, from: number, to: number): number {\n const targets = new Map(listFindings(store, to).map((f) => [f.key, f.excerptHash]));\n const existing = new Set(listVerdicts(store, to).map((v) => v.key));\n const carried = listVerdicts(store, from)\n .filter((v) => !existing.has(v.key) && targets.get(v.key) === v.excerptHash)\n .map((v) => ({ ...v, carriedFrom: v.carriedFrom ?? from }));\n saveVerdicts(store, to, carried);\n return carried.length;\n}\n","import { metricAliasTarget, roleAliasTarget } from \"../aliases.js\";\nimport type {\n CheckRule,\n ForbidImportRule,\n LayeredDepsRule,\n MetricMaxRule,\n MetricMinRule,\n MetricOutlierRule,\n MetricProductMaxRule,\n NoInternalOnlyBarrelsRule,\n Severity,\n} from \"./types.js\";\nimport type { NodeKind, NodeRole } from \"../types.js\";\n\nexport interface ValidateRulesOptions {\n /** Called with a human-readable message when a deprecated alias is healed. */\n onWarn?: (message: string) => void;\n}\n\ntype Warn = (message: string) => void;\n\nexport function validateRules(\n input: unknown,\n options: ValidateRulesOptions = {},\n): readonly CheckRule[] {\n if (!input || typeof input !== \"object\") {\n throw new Error(\"rules file must be an object with a `rules` array\");\n }\n const obj = input as { rules?: unknown };\n if (!Array.isArray(obj.rules)) {\n throw new Error(\"rules file must have a `rules` array\");\n }\n const warn: Warn = options.onWarn ?? (() => {});\n return obj.rules.map((r, i) => validateRule(r, i, warn));\n}\n\n/** Heal a deprecated metric name to its canonical form, warning if renamed. */\nfunction healMetricName(name: string, ruleId: string, warn: Warn): string {\n const target = metricAliasTarget(name);\n if (target) {\n warn(`${ruleId}: metric \"${name}\" is deprecated — using \"${target}\"`);\n return target;\n }\n return name;\n}\n\nfunction validateRule(raw: unknown, index: number, warn: Warn): CheckRule {\n if (!raw || typeof raw !== \"object\") {\n throw new Error(`rule[${index}] must be an object`);\n }\n const r = raw as Record<string, unknown>;\n if (typeof r.id !== \"string\" || !r.id) {\n throw new Error(`rule[${index}] missing string id`);\n }\n if (typeof r.type !== \"string\") {\n throw new Error(`rule[${index}] (${r.id}) missing string type`);\n }\n switch (r.type) {\n case \"metric-max\":\n return assertMetricMax(r, warn);\n case \"metric-min\":\n return assertMetricMin(r, warn);\n case \"metric-product-max\":\n return assertMetricProductMax(r, warn);\n case \"metric-outlier\":\n return assertMetricOutlier(r, warn);\n case \"forbid-import\":\n return assertForbidImport(r);\n case \"layered-deps\":\n return assertLayeredDeps(r, warn);\n case \"no-internal-only-barrels\":\n return assertNoInternalOnlyBarrels(r);\n default:\n throw new Error(`rule[${index}] (${r.id}) unknown type \"${r.type}\"`);\n }\n}\n\nfunction assertNoInternalOnlyBarrels(\n r: Record<string, unknown>,\n): NoInternalOnlyBarrelsRule {\n if (!Array.isArray(r.packageRoots) || r.packageRoots.length === 0) {\n throw new Error(\n `${r.id}: packageRoots must be a non-empty array of path-prefix strings`,\n );\n }\n for (const p of r.packageRoots) {\n if (typeof p !== \"string\" || !p) {\n throw new Error(`${r.id}: each packageRoots entry must be a non-empty string`);\n }\n }\n return {\n type: \"no-internal-only-barrels\",\n id: r.id as string,\n packageRoots: r.packageRoots as string[],\n severity: parseSeverity(r),\n exclude: parseExclude(r),\n };\n}\n\nfunction assertLayeredDeps(r: Record<string, unknown>, warn: Warn): LayeredDepsRule {\n if (!Array.isArray(r.layers) || r.layers.length < 2) {\n throw new Error(`${r.id}: layers must be an array of 2+ string arrays`);\n }\n for (const layer of r.layers) {\n if (!Array.isArray(layer) || !layer.every((p) => typeof p === \"string\")) {\n throw new Error(`${r.id}: each layer must be a string[]`);\n }\n if (layer.length === 0) {\n throw new Error(`${r.id}: empty layers not allowed`);\n }\n }\n const seen = new Set<string>();\n for (const layer of r.layers as string[][]) {\n for (const pkg of layer) {\n if (seen.has(pkg)) {\n throw new Error(`${r.id}: package \"${pkg}\" appears in more than one layer`);\n }\n seen.add(pkg);\n }\n }\n return {\n type: \"layered-deps\",\n id: r.id as string,\n layers: r.layers as string[][],\n severity: parseSeverity(r),\n excludeRoles: parseRoleArray(r.id as string, r.excludeRoles, warn),\n };\n}\n\nfunction assertMetricProductMax(\n r: Record<string, unknown>,\n warn: Warn,\n): MetricProductMaxRule {\n if (!Array.isArray(r.metrics) || r.metrics.length < 2) {\n throw new Error(`${r.id}: metrics must be an array of 2+ metric names`);\n }\n if (!r.metrics.every((m): m is string => typeof m === \"string\")) {\n throw new Error(`${r.id}: metrics must be strings`);\n }\n if (typeof r.max !== \"number\") {\n throw new Error(`${r.id}: max must be a number`);\n }\n const ruleId = r.id as string;\n return {\n type: \"metric-product-max\",\n id: ruleId,\n metrics: r.metrics.map((m) => healMetricName(m, ruleId, warn)),\n max: r.max,\n kind: parseOptionalKind(r),\n severity: parseSeverity(r),\n exclude: parseExclude(r),\n excludeRoles: parseRoleArray(ruleId, r.excludeRoles, warn),\n };\n}\n\nfunction assertMetricMax(r: Record<string, unknown>, warn: Warn): MetricMaxRule {\n if (typeof r.metric !== \"string\") throw new Error(`${r.id}: metric must be a string`);\n if (typeof r.max !== \"number\") throw new Error(`${r.id}: max must be a number`);\n const ruleId = r.id as string;\n return {\n type: \"metric-max\",\n id: ruleId,\n metric: healMetricName(r.metric, ruleId, warn),\n max: r.max,\n kind: parseOptionalKind(r),\n severity: parseSeverity(r),\n exclude: parseExclude(r),\n excludeRoles: parseRoleArray(ruleId, r.excludeRoles, warn),\n };\n}\n\nfunction assertMetricMin(r: Record<string, unknown>, warn: Warn): MetricMinRule {\n if (typeof r.metric !== \"string\") throw new Error(`${r.id}: metric must be a string`);\n if (typeof r.min !== \"number\") throw new Error(`${r.id}: min must be a number`);\n const ruleId = r.id as string;\n return {\n type: \"metric-min\",\n id: ruleId,\n metric: healMetricName(r.metric, ruleId, warn),\n min: r.min,\n kind: parseOptionalKind(r),\n severity: parseSeverity(r),\n exclude: parseExclude(r),\n excludeRoles: parseRoleArray(ruleId, r.excludeRoles, warn),\n };\n}\n\nconst NODE_KINDS: ReadonlySet<NodeKind> = new Set([\"package\", \"module\", \"file\", \"symbol\", \"external\"]);\n\nfunction assertMetricOutlier(r: Record<string, unknown>, warn: Warn): MetricOutlierRule {\n if (typeof r.metric !== \"string\") throw new Error(`${r.id}: metric must be a string`);\n if (!isNodeKind(r.kind)) throw kindError(r.id);\n if (typeof r.percentile !== \"number\" || r.percentile < 50 || r.percentile > 100) {\n throw new Error(`${r.id}: percentile must be a number from 50 to 100`);\n }\n if (r.minSample !== undefined && (!Number.isInteger(r.minSample) || (r.minSample as number) < 1)) {\n throw new Error(`${r.id}: minSample must be a positive integer`);\n }\n if (r.floor !== undefined && (typeof r.floor !== \"number\" || !Number.isFinite(r.floor) || r.floor < 0)) {\n throw new Error(`${r.id}: floor must be a non-negative finite number`);\n }\n if (r.rankNonZero !== undefined && typeof r.rankNonZero !== \"boolean\") {\n throw new Error(`${r.id}: rankNonZero must be a boolean`);\n }\n const ruleId = r.id as string;\n return {\n type: \"metric-outlier\",\n id: ruleId,\n metric: healMetricName(r.metric, ruleId, warn),\n kind: r.kind,\n percentile: r.percentile,\n minSample: r.minSample as number | undefined,\n floor: r.floor as number | undefined,\n rankNonZero: r.rankNonZero as boolean | undefined,\n severity: parseSeverity(r),\n };\n}\n\nfunction assertForbidImport(r: Record<string, unknown>): ForbidImportRule {\n if (typeof r.from !== \"string\") throw new Error(`${r.id}: from must be a string`);\n if (typeof r.to !== \"string\") throw new Error(`${r.id}: to must be a string`);\n return {\n type: \"forbid-import\",\n id: r.id as string,\n from: r.from,\n to: r.to,\n except: parseStringList(r, \"except\"),\n severity: parseSeverity(r),\n };\n}\n\nfunction isNodeKind(value: unknown): value is NodeKind {\n return typeof value === \"string\" && NODE_KINDS.has(value as NodeKind);\n}\n\nfunction kindError(ruleId: unknown): Error {\n return new Error(`${ruleId}: kind must be one of ${[...NODE_KINDS].join(\", \")}`);\n}\n\n/** A misspelled kind matches no node, so the rule would silently never fire. */\nfunction parseOptionalKind(r: Record<string, unknown>): NodeKind | undefined {\n if (r.kind === undefined) return undefined;\n if (!isNodeKind(r.kind)) throw kindError(r.id);\n return r.kind;\n}\n\n/** Anything but \"error\" would count as a warning and leave the check passing. */\nfunction parseSeverity(r: Record<string, unknown>): Severity | undefined {\n if (r.severity === undefined || r.severity === \"error\" || r.severity === \"warning\") {\n return r.severity;\n }\n throw new Error(`${r.id}: severity must be \"error\" or \"warning\"`);\n}\n\nfunction parseExclude(r: Record<string, unknown>): string[] | undefined {\n return parseStringList(r, \"exclude\");\n}\n\nfunction parseStringList(r: Record<string, unknown>, key: string): string[] | undefined {\n const value = r[key];\n if (value === undefined) return undefined;\n if (!Array.isArray(value) || !value.every((e) => typeof e === \"string\")) {\n throw new Error(`${r.id}: ${key} must be an array of strings`);\n }\n return value;\n}\n\nconst ROLE_VALUES: ReadonlySet<NodeRole> = new Set([\n \"test\",\n \"fixture\",\n \"story\",\n \"lab\",\n \"barrel\",\n \"types\",\n \"config\",\n \"entry\",\n \"source\",\n]);\n\nfunction parseRoleArray(\n ruleId: string,\n value: unknown,\n warn: Warn,\n): NodeRole[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value)) {\n throw new Error(`${ruleId}: excludeRoles must be an array`);\n }\n return value.map((entry) => healRole(entry, ruleId, warn));\n}\n\n/** Heal a deprecated role alias to canonical; throw only on genuinely-unknown. */\nfunction healRole(entry: unknown, ruleId: string, warn: Warn): NodeRole {\n if (typeof entry === \"string\" && ROLE_VALUES.has(entry as NodeRole)) {\n return entry as NodeRole;\n }\n if (typeof entry === \"string\") {\n const target = roleAliasTarget(entry);\n if (target) {\n warn(`${ruleId}: role \"${entry}\" is deprecated — using \"${target}\"`);\n return target;\n }\n }\n throw new Error(\n `${ruleId}: unknown role \"${entry}\" — valid: ${[...ROLE_VALUES].join(\", \")}`,\n );\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { SnapshotRow } from \"../types.js\";\nimport { runChecks } from \"./check.js\";\nimport type { CheckResult, CheckRule } from \"./types.js\";\nimport { validateRules, type ValidateRulesOptions } from \"./validate.js\";\n\n/** A snapshot id, or a ref name resolved to that ref's newest snapshot. */\nexport type SnapshotSpec = number | string;\n\nexport interface CheckSnapshotOptions {\n snapshot: SnapshotSpec;\n rules: readonly CheckRule[];\n baseline?: SnapshotSpec;\n}\n\nexport interface CheckSnapshotResult {\n snapshot: SnapshotRow;\n baselineSnapshot?: SnapshotRow;\n result: CheckResult;\n}\n\nexport function resolveSnapshot(store: CodeGraphStore, spec: SnapshotSpec): SnapshotRow {\n if (typeof spec === \"number\" || /^\\d+$/.test(spec)) {\n const snap = store.getSnapshot(Number(spec));\n if (!snap) throw new Error(`no snapshot with id ${spec}`);\n return snap;\n }\n const snap = store.getLatestSnapshotByRef(spec);\n if (!snap) throw new Error(`no snapshot found for ref \"${spec}\"`);\n return snap;\n}\n\n/** Check one snapshot against a rule set, marking violations already present in the baseline as carryover. */\nexport function checkSnapshot(store: CodeGraphStore, options: CheckSnapshotOptions): CheckSnapshotResult {\n const snapshot = resolveSnapshot(store, options.snapshot);\n const baselineSnapshot = options.baseline !== undefined ? resolveSnapshot(store, options.baseline) : undefined;\n const result = runChecks(store, {\n snapshotId: snapshot.id,\n rules: options.rules,\n baselineSnapshotId: baselineSnapshot?.id,\n });\n return { snapshot, baselineSnapshot, result };\n}\n\n/** Read and validate a `check.json` rules file; deprecated aliases heal through `onWarn`. */\nexport async function loadCheckRules(\n path: string,\n options: ValidateRulesOptions = {},\n): Promise<readonly CheckRule[]> {\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (err) {\n throw new Error(`Cannot read rules file at ${path}: ${errorMessage(err)}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new Error(`Invalid JSON in ${path}: ${errorMessage(err)}`);\n }\n return validateRules(parsed, options);\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","import { canonicalEdgeKind, canonicalMetricName } from \"../aliases.js\";\nimport type { AliasChain } from \"../identity/alias-chain.js\";\nimport { aliasChain } from \"../identity/store-identity.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { GraphEdge, GraphMetric, GraphNode } from \"../types.js\";\nimport type { GraphDiff, GraphDiffSummary, MetricDelta, NodeRename } from \"./types.js\";\n\ntype AliasMap = Pick<AliasChain, \"resolve\" | \"trace\">;\n\nfunction resolveId(id: string, aliases: AliasMap): string {\n return aliases.resolve(id);\n}\n\nfunction edgeKey(srcId: string, dstId: string, kind: string): string {\n return JSON.stringify([srcId, dstId, canonicalEdgeKind(kind)]);\n}\n\nfunction metricKey(nodeId: string, name: string): string {\n return JSON.stringify([nodeId, canonicalMetricName(name)]);\n}\n\nfunction indexEdges(edges: readonly GraphEdge[]): Map<string, GraphEdge> {\n const m = new Map<string, GraphEdge>();\n for (const e of edges) m.set(edgeKey(e.srcId, e.dstId, e.kind), e);\n return m;\n}\n\ninterface NodeDiff {\n added: GraphNode[];\n removed: GraphNode[];\n renamed: NodeRename[];\n commonNewIds: Set<string>;\n}\n\nfunction diffNodes(fromNodes: readonly GraphNode[], toNodes: readonly GraphNode[], aliases: AliasMap): NodeDiff {\n const toIndex = new Map(toNodes.map((n) => [n.id, n]));\n const matchedToIds = new Set<string>();\n const removed: GraphNode[] = [];\n const renamed: NodeRename[] = [];\n for (const fromNode of fromNodes) {\n const newId = resolveId(fromNode.id, aliases);\n const toNode = toIndex.get(newId);\n if (!toNode) {\n removed.push(fromNode);\n continue;\n }\n matchedToIds.add(newId);\n if (newId !== fromNode.id) {\n renamed.push({ oldId: fromNode.id, newId, reason: aliases.trace(fromNode.id).reason!, node: toNode });\n }\n }\n const added = toNodes.filter((toNode) => !matchedToIds.has(toNode.id));\n return { added, removed, renamed, commonNewIds: matchedToIds };\n}\n\nfunction diffEdges(\n fromEdges: readonly GraphEdge[],\n toEdges: readonly GraphEdge[],\n aliases: AliasMap,\n): { added: GraphEdge[]; removed: GraphEdge[] } {\n const remappedKey = (e: GraphEdge) => edgeKey(resolveId(e.srcId, aliases), resolveId(e.dstId, aliases), e.kind);\n const fromKeys = new Set(fromEdges.map(remappedKey));\n const toIndex = indexEdges(toEdges);\n const added: GraphEdge[] = [];\n for (const [k, e] of toIndex) {\n if (!fromKeys.has(k)) added.push(e);\n }\n const removed = fromEdges.filter((e) => !toIndex.has(remappedKey(e)));\n return { added, removed };\n}\n\ninterface IndexedMetric {\n metric: GraphMetric;\n nodeId: string;\n}\n\nfunction indexFromMetrics(metrics: readonly GraphMetric[], aliases: AliasMap): Map<string, IndexedMetric> {\n const fromIndex = new Map<string, IndexedMetric>();\n for (const m of metrics) {\n const newId = resolveId(m.nodeId, aliases);\n fromIndex.set(metricKey(newId, m.name), { metric: m, nodeId: newId });\n }\n return fromIndex;\n}\n\nfunction deltaOf(before: number | null, after: number | null): number | null {\n if (before === null || after === null) return null;\n return after - before;\n}\n\nfunction metricDelta(nodeId: string, name: string, before: number | null, after: number | null): MetricDelta {\n return { nodeId, name: canonicalMetricName(name), before, after, delta: deltaOf(before, after) };\n}\n\n/** Metric changes on nodes present in both snapshots; metrics on added or removed nodes are the node's news, not drift. */\nfunction diffMetrics(\n fromMetrics: readonly GraphMetric[],\n toMetrics: readonly GraphMetric[],\n aliases: AliasMap,\n commonNewIds: Set<string>,\n): MetricDelta[] {\n const fromIndex = indexFromMetrics(fromMetrics, aliases);\n const toIndex = new Map(toMetrics.map((m) => [metricKey(m.nodeId, m.name), m]));\n const out: MetricDelta[] = [];\n const seen = new Set<string>();\n for (const [key, { metric: before, nodeId }] of fromIndex) {\n if (!commonNewIds.has(nodeId)) continue;\n seen.add(key);\n const afterVal = toIndex.get(key)?.value ?? null;\n if (before.value !== afterVal) out.push(metricDelta(nodeId, before.name, before.value, afterVal));\n }\n for (const [key, after] of toIndex) {\n if (seen.has(key) || !commonNewIds.has(after.nodeId)) continue;\n out.push(metricDelta(after.nodeId, after.name, null, after.value));\n }\n return out;\n}\n\nexport interface DiffSnapshotsOptions {\n fromSnapshotId: number;\n toSnapshotId: number;\n}\n\n/**\n * Structural diff of two snapshots. Ids follow the alias chain between them, across\n * every rename in between, so a move is not a delete plus an add.\n */\nexport function diffSnapshots(store: CodeGraphStore, options: DiffSnapshotsOptions): GraphDiff {\n const { fromSnapshotId, toSnapshotId } = options;\n const aliases = aliasChain(store, fromSnapshotId, toSnapshotId);\n const nodeDiff = diffNodes(store.listNodes(fromSnapshotId), store.listNodes(toSnapshotId), aliases);\n const edgeDiff = diffEdges(store.listEdges(fromSnapshotId), store.listEdges(toSnapshotId), aliases);\n const metricDeltas = diffMetrics(\n store.listMetrics(fromSnapshotId),\n store.listMetrics(toSnapshotId),\n aliases,\n nodeDiff.commonNewIds,\n );\n return {\n summary: summarize(options, nodeDiff, edgeDiff, metricDeltas),\n addedNodes: nodeDiff.added,\n removedNodes: nodeDiff.removed,\n renamedNodes: nodeDiff.renamed,\n addedEdges: edgeDiff.added,\n removedEdges: edgeDiff.removed,\n metricDeltas,\n };\n}\n\nfunction summarize(\n { fromSnapshotId, toSnapshotId }: DiffSnapshotsOptions,\n nodeDiff: NodeDiff,\n edgeDiff: { added: GraphEdge[]; removed: GraphEdge[] },\n metricDeltas: readonly MetricDelta[],\n): GraphDiffSummary {\n return {\n fromSnapshotId,\n toSnapshotId,\n addedNodes: nodeDiff.added.length,\n removedNodes: nodeDiff.removed.length,\n renamedNodes: nodeDiff.renamed.length,\n unchangedNodes: nodeDiff.commonNewIds.size - nodeDiff.renamed.length,\n addedEdges: edgeDiff.added.length,\n removedEdges: edgeDiff.removed.length,\n metricChanges: metricDeltas.length,\n };\n}\n","import { runChecks } from \"../check/check.js\";\nimport type { CheckRule } from \"../check/types.js\";\nimport { aliasChain } from \"../identity/store-identity.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { bucketViolations, type ViolationBuckets } from \"./violation-buckets.js\";\n\nexport type { UnchangedViolation } from \"./violation-buckets.js\";\n\nexport interface CheckDiff extends ViolationBuckets {\n fromSnapshotId: number;\n toSnapshotId: number;\n rulesEvaluated: number;\n}\n\nexport interface DiffCheckResultsOptions {\n fromSnapshotId: number;\n toSnapshotId: number;\n rules: readonly CheckRule[];\n}\n\n/**\n * Run the rules on both snapshots and bucket each violation as new, resolved, or\n * unchanged (worsened or improved by value). From-side ids follow the alias chain\n * into the to-snapshot, so a moved file's violations stay unchanged.\n */\nexport function diffCheckResults(store: CodeGraphStore, options: DiffCheckResultsOptions): CheckDiff {\n const from = runChecks(store, { snapshotId: options.fromSnapshotId, rules: options.rules });\n const to = runChecks(store, { snapshotId: options.toSnapshotId, rules: options.rules });\n const chain = aliasChain(store, options.fromSnapshotId, options.toSnapshotId);\n return {\n fromSnapshotId: options.fromSnapshotId,\n toSnapshotId: options.toSnapshotId,\n rulesEvaluated: options.rules.length,\n ...bucketViolations(from.violations, to.violations, chain.resolve),\n };\n}\n","import { canonicalEdgeKind } from \"../aliases.js\";\nimport {\n computeSymbolConsumers,\n computeSymbolCoupling,\n type ReferenceEdgeLite,\n} from \"../analysis/symbol-coupling.js\";\nimport { hashText } from \"../check/finding-store.js\";\nimport type { GraphEdge, GraphNode } from \"../types.js\";\n\n/**\n * A symbol's documentable footprint (C-75): structural inputs only, so a moved declaration,\n * a churn window or a centrality shift never reads as a change.\n */\nexport interface FootprintParts {\n /** Hash of `{name, exported, signature, purpose}`; no span. */\n signature: string;\n /** Hash of the sorted distinct file ids that reference the symbol. */\n consumers: string;\n /** Hash of the sorted co-import partner symbol ids at or above `minCoImports`. */\n coupling: string;\n}\n\nexport interface SymbolFootprint {\n symbolId: string;\n parts: FootprintParts;\n /** Hash of the three part hashes. */\n hash: string;\n}\n\nexport interface FootprintGraph {\n nodes: readonly GraphNode[];\n edges: readonly GraphEdge[];\n}\n\nexport interface FootprintOptions {\n /** Drop a referencing file from consumers and co-import coupling, e.g. test files. Default keeps all. */\n ignoreConsumer?: (fileId: string) => boolean;\n /** Co-import threshold for a coupling partner. Default 2. */\n minCoImports?: number;\n}\n\n/** A doc target: the default unit is one file holding its symbols. */\nexport interface FootprintUnit {\n unitId: string;\n symbolIds: readonly string[];\n}\n\nconst DEFAULT_MIN_CO_IMPORTS = 2;\n\n/** Footprint of every symbol node in the graph, keyed by symbol id. */\nexport function computeFootprints(\n graph: FootprintGraph,\n options: FootprintOptions = {},\n): Map<string, SymbolFootprint> {\n const edges = referenceEdges(graph.edges, options.ignoreConsumer);\n const consumers = consumersBySymbol(edges);\n const partners = partnersBySymbol(edges, options.minCoImports ?? DEFAULT_MIN_CO_IMPORTS);\n const out = new Map<string, SymbolFootprint>();\n for (const node of graph.nodes) {\n if (node.kind !== \"symbol\") continue;\n const parts: FootprintParts = {\n signature: hashJson(signatureOf(node)),\n consumers: hashJson(consumers.get(node.id) ?? []),\n coupling: hashJson(partners.get(node.id) ?? []),\n };\n const hash = hashJson([parts.signature, parts.consumers, parts.coupling]);\n out.set(node.id, { symbolId: node.id, parts, hash });\n }\n return out;\n}\n\n/**\n * Order-independent hash of a unit's `[symbolId, footprint.hash]` pairs. A member with no\n * footprint hashes as null, so a symbol that disappears still changes the set.\n */\nexport function symbolSetHash(\n unit: FootprintUnit,\n footprints: ReadonlyMap<string, SymbolFootprint>,\n): string {\n const pairs = [...new Set(unit.symbolIds)]\n .sort()\n .map((id) => [id, footprints.get(id)?.hash ?? null]);\n return hashJson(pairs);\n}\n\nfunction hashJson(value: unknown): string {\n return hashText(JSON.stringify(value));\n}\n\nfunction signatureOf(node: GraphNode): unknown {\n const attrs = node.attrs ?? {};\n return {\n name: node.name,\n exported: attrs.exported === true,\n signature: typeof attrs.signature === \"string\" ? attrs.signature : null,\n purpose: typeof attrs.purpose === \"string\" ? attrs.purpose : null,\n };\n}\n\nfunction referenceEdges(\n edges: readonly GraphEdge[],\n ignoreConsumer: FootprintOptions[\"ignoreConsumer\"],\n): ReferenceEdgeLite[] {\n return edges.filter(\n (e) => canonicalEdgeKind(e.kind) === \"references\" && !ignoreConsumer?.(e.srcId),\n );\n}\n\nfunction consumersBySymbol(edges: readonly ReferenceEdgeLite[]): Map<string, string[]> {\n return new Map(computeSymbolConsumers(edges).map((c) => [c.symbolId, c.consumers]));\n}\n\nfunction partnersBySymbol(\n edges: readonly ReferenceEdgeLite[],\n minCoImports: number,\n): Map<string, string[]> {\n const partners = new Map<string, Set<string>>();\n const add = (from: string, to: string): void => {\n const set = partners.get(from) ?? new Set<string>();\n set.add(to);\n partners.set(from, set);\n };\n for (const pair of computeSymbolCoupling(edges, { minCoImports })) {\n add(pair.aId, pair.bId);\n add(pair.bId, pair.aId);\n }\n return new Map([...partners].map(([id, set]) => [id, [...set].sort()]));\n}\n","import { parseSymbolId, symbolId } from \"../extractors/ids.js\";\nimport type { AliasChain } from \"../identity/alias-chain.js\";\nimport { aliasChain } from \"../identity/store-identity.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { GraphNode } from \"../types.js\";\nimport { computeFootprints, type FootprintGraph, type FootprintOptions, type SymbolFootprint } from \"./footprint.js\";\nimport type { FootprintChange, FootprintChangeReason, FootprintDiff } from \"./types.js\";\n\nexport interface DiffFootprintsOptions extends FootprintOptions {\n fromSnapshotId: number;\n toSnapshotId: number;\n}\n\ntype ResolveId = (id: string) => string;\n\nconst PART_REASONS = [\"signature\", \"consumers\", \"coupling\"] as const;\n\n/**\n * Symbols whose documentable footprint differs between two snapshots. From-snapshot ids\n * follow the alias chain first, so a moved file reads as `renamed`, not a remove plus an add.\n */\nexport function diffFootprints(store: CodeGraphStore, options: DiffFootprintsOptions): FootprintDiff {\n const { fromSnapshotId, toSnapshotId } = options;\n const resolve = symbolAwareResolver(aliasChain(store, fromSnapshotId, toSnapshotId));\n const fromGraph = loadSymbolLayer(store, fromSnapshotId);\n const toGraph = loadSymbolLayer(store, toSnapshotId);\n const { previousIds, mergedAway } = mergeSources(fromGraph.nodes, resolve);\n const before = computeFootprints(remapGraph(fromGraph, resolve, new Set(mergedAway)), options);\n const after = computeFootprints(toGraph, options);\n const changes = [\n ...changedOrAdded(after, before, previousIds),\n ...removed(before, after, previousIds, resolve),\n ...mergedAway.map((id) => ({ symbolId: id, status: \"removed\" as const, reasons: [], fileId: resolve(declaringFile(id)) })),\n ].sort((a, b) => compare(a.symbolId, b.symbolId));\n const files = [...new Set(changes.map((c) => c.fileId))].sort(compare);\n return { fromSnapshotId, toSnapshotId, changes, files };\n}\n\nfunction loadSymbolLayer(store: CodeGraphStore, snapshotId: number): FootprintGraph {\n return {\n nodes: store.listNodes(snapshotId, { includeSymbols: true }).filter((n) => n.kind === \"symbol\"),\n edges: store.listEdges(snapshotId, { includeReferences: true }),\n };\n}\n\n// File renames alias only the file id, so a symbol under a moved file resolves through its file.\nfunction symbolAwareResolver(aliases: Pick<AliasChain, \"resolve\">): ResolveId {\n return (id) => {\n const direct = aliases.resolve(id);\n if (direct !== id) return direct;\n const parsed = parseSymbolId(id);\n return parsed ? symbolId(aliases.resolve(parsed.fileId), parsed.name) : id;\n };\n}\n\n// Losing merge sources are left out so the merged id's prior footprint is the keeper's alone.\nfunction remapGraph(graph: FootprintGraph, resolve: ResolveId, losers: ReadonlySet<string>): FootprintGraph {\n return {\n nodes: graph.nodes.filter((n) => !losers.has(n.id)).map((n) => ({ ...n, id: resolve(n.id) })),\n edges: graph.edges\n .filter((e) => !losers.has(e.srcId) && !losers.has(e.dstId))\n .map((e) => ({ ...e, srcId: resolve(e.srcId), dstId: resolve(e.dstId) })),\n };\n}\n\ninterface MergeSources {\n /** Resolved id to the original from-snapshot id, for symbols whose id moved. */\n previousIds: Map<string, string>;\n /** From-snapshot ids that lost a many-to-one collision and so are reported removed. */\n mergedAway: string[];\n}\n\n// Design (TP-765): one change per to-symbol, so previousId names one source: the symbol already at\n// the target id, else the smallest from-id. The other colliding from-symbols are reported removed.\nfunction mergeSources(nodes: readonly GraphNode[], resolve: ResolveId): MergeSources {\n const groups = new Map<string, string[]>();\n for (const node of nodes) {\n const id = resolve(node.id);\n groups.set(id, [...(groups.get(id) ?? []), node.id]);\n }\n const previousIds = new Map<string, string>();\n const mergedAway: string[] = [];\n for (const [id, sources] of groups) {\n const keeper = sources.includes(id) ? id : [...sources].sort(compare)[0]!;\n if (keeper !== id) previousIds.set(id, keeper);\n mergedAway.push(...sources.filter((source) => source !== keeper));\n }\n return { previousIds, mergedAway };\n}\n\nfunction changedOrAdded(\n after: ReadonlyMap<string, SymbolFootprint>,\n before: ReadonlyMap<string, SymbolFootprint>,\n previousIds: ReadonlyMap<string, string>,\n): FootprintChange[] {\n const out: FootprintChange[] = [];\n for (const [id, footprint] of after) {\n const prior = before.get(id);\n const previousId = previousIds.get(id);\n if (!prior) {\n out.push({ symbolId: id, status: \"added\", reasons: [], fileId: declaringFile(id) });\n continue;\n }\n const reasons = reasonsFor(prior, footprint, previousId !== undefined);\n if (reasons.length === 0) continue;\n out.push({ symbolId: id, ...(previousId ? { previousId } : {}), status: \"changed\", reasons, fileId: declaringFile(id) });\n }\n return out;\n}\n\nfunction reasonsFor(prior: SymbolFootprint, current: SymbolFootprint, renamed: boolean): FootprintChangeReason[] {\n const reasons: FootprintChangeReason[] = PART_REASONS.filter((part) => prior.parts[part] !== current.parts[part]);\n if (renamed) reasons.push(\"renamed\");\n return reasons;\n}\n\nfunction removed(\n before: ReadonlyMap<string, SymbolFootprint>,\n after: ReadonlyMap<string, SymbolFootprint>,\n previousIds: ReadonlyMap<string, string>,\n resolve: ResolveId,\n): FootprintChange[] {\n const out: FootprintChange[] = [];\n for (const id of before.keys()) {\n if (after.has(id)) continue;\n const fromId = previousIds.get(id) ?? id;\n out.push({ symbolId: fromId, status: \"removed\", reasons: [], fileId: resolve(declaringFile(fromId)) });\n }\n return out;\n}\n\nfunction declaringFile(id: string): string {\n return parseSymbolId(id)?.fileId ?? id;\n}\n\nfunction compare(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n","import type { SnapshotRow } from \"../types.js\";\nimport { symbolSetHash, type FootprintUnit, type SymbolFootprint } from \"./footprint.js\";\n\n/**\n * What a consumer generated a unit's doc from. Provenance lives with the consumer, not the\n * store, so it survives snapshot prune.\n */\nexport interface UnitProvenance {\n unitId: string;\n /** The to-snapshot's commit hash; null for a working-tree snapshot. */\n commit: string | null;\n symbolSetHash: string;\n /** The generator the consumer used; the gate records it but never calls one. */\n model: string | null;\n}\n\nexport interface UnitProvenanceInput {\n unit: FootprintUnit;\n footprints: ReadonlyMap<string, SymbolFootprint>;\n snapshot: Pick<SnapshotRow, \"commitHash\">;\n model?: string | null;\n}\n\nexport type RegenerateReason = \"new\" | \"changed\";\n\nexport interface UnitRegeneration {\n unitId: string;\n reason: RegenerateReason;\n}\n\nexport interface GateUnitsInput {\n prior: readonly UnitProvenance[];\n units: readonly FootprintUnit[];\n footprints: ReadonlyMap<string, SymbolFootprint>;\n}\n\n/** An empty `regenerate` means the caller makes no LLM call. */\nexport interface GateResult {\n regenerate: UnitRegeneration[];\n skip: string[];\n /** Prior units that no longer exist. */\n orphaned: string[];\n}\n\n/** A fresh provenance record for one unit at the given snapshot. */\nexport function unitProvenance(input: UnitProvenanceInput): UnitProvenance {\n return {\n unitId: input.unit.unitId,\n commit: input.snapshot.commitHash,\n symbolSetHash: symbolSetHash(input.unit, input.footprints),\n model: input.model ?? null,\n };\n}\n\n/** Splits units into those whose symbol-set hash moved since the prior record and those that did not. */\nexport function gateUnits(input: GateUnitsInput): GateResult {\n const priorHash = new Map(input.prior.map((p) => [p.unitId, p.symbolSetHash]));\n const current = new Set(input.units.map((u) => u.unitId));\n const regenerate: UnitRegeneration[] = [];\n const skip: string[] = [];\n for (const unit of input.units) {\n const before = priorHash.get(unit.unitId);\n if (before === undefined) regenerate.push({ unitId: unit.unitId, reason: \"new\" });\n else if (before !== symbolSetHash(unit, input.footprints)) regenerate.push({ unitId: unit.unitId, reason: \"changed\" });\n else skip.push(unit.unitId);\n }\n const orphaned = [...priorHash.keys()].filter((id) => !current.has(id));\n return { regenerate, skip, orphaned };\n}\n","import { contentHashOf } from \"@titan-design/store-sqlite\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { GraphNode } from \"../types.js\";\nimport type { EmbeddableSymbol } from \"./types.js\";\n\n/** Mirrors the gate harness: purpose text is appended to the signature when present. */\nexport function buildEmbedText(signature: string, purpose?: string | null): string {\n return purpose ? `${signature} -- ${purpose}` : signature;\n}\n\nexport function hashEmbedText(text: string): string {\n return contentHashOf(text);\n}\n\nconst TEST_OR_FIXTURE_PATH = /\\.test\\.|\\.spec\\.|__tests__|\\/fixtures\\//;\nconst EXCLUDED_FILE_ROLES = new Set([\"test\", \"generated\"]);\n\ninterface SymbolTextAttrs {\n exported?: boolean;\n signature?: string;\n purpose?: string;\n}\n\n/**\n * The embeddable corpus of a snapshot: exported symbols that carry a signature,\n * excluding test/fixture/generated code (matching the validated gate corpus).\n */\nexport function listEmbeddableSymbols(store: CodeGraphStore, snapshotId: number): EmbeddableSymbol[] {\n const nodes = store.listNodes(snapshotId, { includeSymbols: true });\n const fileRoles = new Map<string, string | null>();\n for (const n of nodes) if (n.kind === \"file\") fileRoles.set(n.id, n.role ?? null);\n const out: EmbeddableSymbol[] = [];\n for (const n of nodes) {\n const symbol = toEmbeddable(n, fileRoles);\n if (symbol) out.push(symbol);\n }\n return out;\n}\n\nfunction toEmbeddable(node: GraphNode, fileRoles: ReadonlyMap<string, string | null>): EmbeddableSymbol | null {\n if (node.kind !== \"symbol\") return null;\n const attrs = (node.attrs ?? {}) as SymbolTextAttrs;\n if (attrs.exported !== true || !attrs.signature) return null;\n const file = node.parentId ?? node.id.split(\"#\")[0] ?? node.id;\n if (TEST_OR_FIXTURE_PATH.test(file)) return null;\n const role = fileRoles.get(file);\n if (role && EXCLUDED_FILE_ROLES.has(role)) return null;\n const text = buildEmbedText(attrs.signature, attrs.purpose);\n return {\n id: node.id,\n name: node.name,\n file,\n signature: attrs.signature,\n purpose: attrs.purpose,\n text,\n textHash: hashEmbedText(text),\n };\n}\n","import { fromFloat32Buffer, normalize, toFloat32Buffer, type Embedder } from \"@titan-design/embed\";\nimport { CacheBlobTable } from \"@titan-design/store-sqlite\";\nimport { KIT } from \"../schema.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { hashEmbedText } from \"./corpus.js\";\n\n/** The blob_cache namespace for symbol vectors; the model column holds `embedder.model`, which names the vector space including its prefixes. */\nexport const SYMBOL_EMBEDDING_NAMESPACE = \"code-graph/symbol-embedding\";\n\nconst EMBED_BATCH_SIZE = 64;\n\nexport interface CachedEmbedResult {\n /** L2-normalized vectors for every input text, keyed by its text hash. */\n byHash: Map<string, number[]>;\n /** Hashes that had no stored vector and were embedded on this call. */\n newHashes: Set<string>;\n}\n\nfunction symbolVectorCache(store: CodeGraphStore): CacheBlobTable {\n return new CacheBlobTable(store.db, { name: KIT.cacheBlob });\n}\n\nexport function loadVectorsByHash(\n store: CodeGraphStore,\n model: string,\n hashes: readonly string[],\n): Map<string, number[]> {\n const cache = symbolVectorCache(store);\n const found = new Map<string, number[]>();\n for (const contentHash of new Set(hashes)) {\n const hit = cache.get({ namespace: SYMBOL_EMBEDDING_NAMESPACE, model, contentHash });\n if (hit) found.set(contentHash, fromFloat32Buffer(hit.value));\n }\n return found;\n}\n\nfunction storeVectors(\n store: CodeGraphStore,\n model: string,\n rows: ReadonlyArray<{ textHash: string; vector: number[] }>,\n): void {\n const cache = symbolVectorCache(store);\n store.db.transaction(() => {\n for (const r of rows) {\n const key = { namespace: SYMBOL_EMBEDDING_NAMESPACE, model, contentHash: r.textHash };\n cache.put(key, toFloat32Buffer(r.vector), { dims: r.vector.length });\n }\n })();\n}\n\n/**\n * Embed texts through the content-addressed store: only texts whose hash has\n * no vector for this model reach the embedder; new vectors are normalized and\n * persisted batch by batch so the next call (or a retry after a failure) is a cache hit.\n */\nexport async function embedTextsCached(\n store: CodeGraphStore,\n embedder: Embedder,\n texts: readonly string[],\n): Promise<CachedEmbedResult> {\n const hashes = texts.map((t) => hashEmbedText(t));\n const byHash = loadVectorsByHash(store, embedder.model, hashes);\n const missing = new Map<string, string>();\n texts.forEach((text, i) => {\n if (!byHash.has(hashes[i]!)) missing.set(hashes[i]!, text);\n });\n const pending = [...missing.entries()];\n for (let i = 0; i < pending.length; i += EMBED_BATCH_SIZE) {\n const rows = await embedBatch(embedder, pending.slice(i, i + EMBED_BATCH_SIZE));\n storeVectors(store, embedder.model, rows);\n for (const r of rows) byHash.set(r.textHash, r.vector);\n }\n return { byHash, newHashes: new Set(missing.keys()) };\n}\n\nasync function embedBatch(\n embedder: Embedder,\n batch: ReadonlyArray<[string, string]>,\n): Promise<Array<{ textHash: string; vector: number[] }>> {\n const vectors = await embedder.embed(batch.map(([, text]) => text), { role: \"document\" });\n if (vectors.length !== batch.length) {\n throw new Error(`Embedder returned ${vectors.length} vectors for ${batch.length} texts`);\n }\n return batch.map(([textHash], j) => ({ textHash, vector: normalize(vectors[j]!) }));\n}\n","import type { Embedder } from \"@titan-design/embed\";\nimport { BruteForceVectorIndex, vectorRetriever } from \"@titan-design/retrieval\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { embedTextsCached, loadVectorsByHash } from \"./cache.js\";\nimport { listEmbeddableSymbols } from \"./corpus.js\";\nimport type {\n EmbedAttempt,\n EmbeddableSymbol,\n EmbedSnapshotResult,\n FindSimilarOptions,\n SimilarCandidate,\n SimilarResult,\n} from \"./types.js\";\n\n/**\n * Precompute capability embeddings for a snapshot. Only texts whose hash has no\n * stored vector are sent to the embedder, so re-runs and unchanged symbols cost\n * nothing: the content-addressed store is the incremental-reuse mechanism.\n */\nexport async function embedSnapshot(\n store: CodeGraphStore,\n snapshotId: number,\n embedder: Embedder,\n): Promise<EmbedSnapshotResult> {\n const symbols = listEmbeddableSymbols(store, snapshotId);\n const { newHashes } = await embedTextsCached(store, embedder, symbols.map((s) => s.text));\n return {\n model: embedder.model,\n symbols: symbols.length,\n withPurpose: symbols.filter((s) => s.purpose).length,\n embedded: symbols.length,\n newlyEmbedded: newHashes.size,\n reused: symbols.filter((s) => !newHashes.has(s.textHash)).length,\n };\n}\n\n/**\n * The post-index pass. A backend failure (ollama down, model missing) must not\n * fail the index: the snapshot is already persisted and valid without vectors.\n */\nexport async function tryEmbedSnapshot(\n store: CodeGraphStore,\n snapshotId: number,\n embedder: Embedder,\n): Promise<EmbedAttempt> {\n try {\n return { ok: true, result: await embedSnapshot(store, snapshotId, embedder) };\n } catch (err) {\n return { ok: false, model: embedder.model, error: err instanceof Error ? err.message : String(err) };\n }\n}\n\n/**\n * The query-time \"about to write X: does it exist?\" surface. Embeds the query\n * (an intent sentence, a pseudo-signature, or both as `sig -- intent`), ranks\n * the snapshot's embedded symbols by cosine similarity, and returns the top-K\n * with coverage so the caller can weigh how much of the repo was searchable.\n */\nexport async function findSimilarCapability(\n store: CodeGraphStore,\n snapshotId: number,\n query: string,\n embedder: Embedder,\n opts: FindSimilarOptions = {},\n): Promise<SimilarResult> {\n const symbols = listEmbeddableSymbols(store, snapshotId);\n const index = buildSymbolIndex(store, embedder.model, symbols);\n if (index.size === 0) {\n throw new Error(\n `No capability embeddings stored for snapshot ${snapshotId} ` +\n `(model ${embedder.model}); run embedSnapshot first.`,\n );\n }\n const retriever = vectorRetriever(embedder, index);\n const hits = await retriever.retrieve(query, { limit: opts.limit ?? 10 });\n const byId = new Map(symbols.map((s) => [s.id, s]));\n return {\n query,\n model: embedder.model,\n coverage: { symbols: symbols.length, embedded: index.size, withPurpose: symbols.filter((s) => s.purpose).length },\n candidates: hits.map((h) => toCandidate(byId.get(h.id)!, h.score ?? 0)),\n };\n}\n\nfunction buildSymbolIndex(\n store: CodeGraphStore,\n model: string,\n symbols: readonly EmbeddableSymbol[],\n): BruteForceVectorIndex {\n const vectors = loadVectorsByHash(store, model, symbols.map((s) => s.textHash));\n const index = new BruteForceVectorIndex();\n for (const s of symbols) {\n const vector = vectors.get(s.textHash);\n if (vector) index.add(s.id, vector);\n }\n return index;\n}\n\nfunction toCandidate(s: EmbeddableSymbol, score: number): SimilarCandidate {\n return { id: s.id, name: s.name, file: s.file, signature: s.signature, purpose: s.purpose, score };\n}\n","import type { GraphEdge } from \"../types.js\";\n\n/**\n * Greedy-modularity (Clauset-Newman-Moore) community detection over the\n * undirected file dependency graph. Deterministic: ties and labels resolve\n * by sorted node id, so the same graph always yields the same partition.\n *\n * Two optional controls shape the C-88 capability-altitude cut, in opposite\n * directions: `maxSize` skips any merge that would grow a community past it\n * (greedy CNM otherwise snowballs a dense graph into one giant blob — the\n * cap shapes formation instead of trying to split after the fact), and\n * `targetCount` keeps merging past the natural modularity stop (taking the\n * least-bad allowed merge) while more communities than that remain, so a\n * sparse fragmented graph still coarsens. Disconnected components can never\n * merge, so the floor is the component count.\n */\nexport function detectCommunities(\n fileIds: readonly string[],\n edges: readonly GraphEdge[],\n opts?: { targetCount?: number; maxSize?: number },\n): Map<string, string[]> {\n const nodeSet = new Set(fileIds);\n const adj = buildUndirectedAdjacency(edges, nodeSet);\n const communityOf = greedyModularity(fileIds, adj, opts);\n const out = new Map<string, string[]>();\n for (const f of fileIds) pushMulti(out, communityOf.get(f) ?? f, f);\n return out;\n}\n\nfunction buildUndirectedAdjacency(\n edges: readonly GraphEdge[],\n nodeSet: ReadonlySet<string>,\n): Map<string, Map<string, number>> {\n const adj = new Map<string, Map<string, number>>();\n const link = (a: string, b: string): void => {\n let row = adj.get(a);\n if (!row) {\n row = new Map();\n adj.set(a, row);\n }\n row.set(b, (row.get(b) ?? 0) + 1);\n };\n for (const e of edges) {\n if (e.srcId === e.dstId) continue;\n if (!nodeSet.has(e.srcId) || !nodeSet.has(e.dstId)) continue;\n link(e.srcId, e.dstId);\n link(e.dstId, e.srcId);\n }\n return adj;\n}\n\ninterface CommunityState {\n members: Map<string, string[]>;\n deg: Map<string, number>;\n between: Map<string, Map<string, number>>;\n twoM: number;\n}\n\nfunction greedyModularity(\n nodes: readonly string[],\n adj: ReadonlyMap<string, ReadonlyMap<string, number>>,\n opts?: { targetCount?: number; maxSize?: number },\n): Map<string, string> {\n const state = initCommunities(nodes, adj);\n if (state.twoM === 0) return new Map(nodes.map((n) => [n, n]));\n for (;;) {\n const coarsen =\n opts?.targetCount !== undefined && state.members.size > opts.targetCount;\n const best = bestMerge(state, coarsen, opts?.maxSize);\n if (!best) break;\n applyMerge(state, best.i, best.j);\n }\n return communityLabels(state);\n}\n\nfunction initCommunities(\n nodes: readonly string[],\n adj: ReadonlyMap<string, ReadonlyMap<string, number>>,\n): CommunityState {\n const members = new Map<string, string[]>();\n const deg = new Map<string, number>();\n const between = new Map<string, Map<string, number>>();\n let twoM = 0;\n for (const n of nodes) {\n const row = new Map<string, number>();\n let d = 0;\n for (const [k, w] of adj.get(n) ?? []) {\n row.set(k, w);\n d += w;\n }\n members.set(n, [n]);\n deg.set(n, d);\n between.set(n, row);\n twoM += d;\n }\n return { members, deg, between, twoM };\n}\n\n/**\n * The adjacent community pair with the largest modularity gain, among merges\n * that respect `maxSize`. Without `allowNegative`, only positive-gain merges\n * qualify (the natural CNM stop); with it, the least-bad allowed merge is\n * returned so coarsening can continue.\n */\nfunction bestMerge(\n state: CommunityState,\n allowNegative: boolean,\n maxSize?: number,\n): { i: string; j: string; dQ: number } | null {\n const { members, between, deg, twoM } = state;\n let best: { i: string; j: string; dQ: number } | null = null;\n for (const [i, row] of between) {\n for (const [j, eij] of row) {\n if (i >= j) continue;\n if (\n maxSize !== undefined &&\n members.get(i)!.length + members.get(j)!.length > maxSize\n ) {\n continue;\n }\n const dQ =\n (2 * eij) / twoM -\n (2 * deg.get(i)! * deg.get(j)!) / (twoM * twoM);\n if (!allowNegative && dQ <= 1e-12) continue;\n if (best === null || dQ > best.dQ) best = { i, j, dQ };\n }\n }\n return best;\n}\n\nfunction applyMerge(state: CommunityState, i: string, j: string): void {\n const { members, deg, between } = state;\n members.get(i)!.push(...members.get(j)!);\n members.delete(j);\n deg.set(i, deg.get(i)! + deg.get(j)!);\n deg.delete(j);\n const rowI = between.get(i)!;\n for (const [k, w] of between.get(j)!) {\n if (k === i) continue;\n rowI.set(k, (rowI.get(k) ?? 0) + w);\n const rowK = between.get(k)!;\n rowK.set(i, (rowK.get(i) ?? 0) + w);\n rowK.delete(j);\n }\n rowI.delete(j);\n between.delete(j);\n}\n\nfunction communityLabels(state: CommunityState): Map<string, string> {\n const out = new Map<string, string>();\n const reps = [...state.members.keys()].sort();\n reps.forEach((rep, idx) => {\n for (const n of state.members.get(rep)!) out.set(n, `c${idx}`);\n });\n return out;\n}\n\nfunction pushMulti(map: Map<string, string[]>, key: string, value: string): void {\n let list = map.get(key);\n if (!list) {\n list = [];\n map.set(key, list);\n }\n list.push(value);\n}\n","import * as path from \"node:path\";\nimport { contentHashOf } from \"@titan-design/store-sqlite\";\nimport { resolveBarrelEdges } from \"../barrel-resolve.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport type { GraphEdge, GraphNode } from \"../types.js\";\nimport { detectCommunities } from \"./communities.js\";\nimport type { ConventionArea, ConventionCorpus, ConventionOptions, ConventionSymbol } from \"./types.js\";\n\nconst DEFAULT_MIN_SIZE = 3;\nconst PROMPT_FILE_CAP = 30;\nconst PROMPT_SYMBOL_CAP = 15;\n\n/** Coarse capability-altitude cut: about one area per 25 files, clamped to 6..40. */\nexport function defaultTargetCount(fileCount: number): number {\n return Math.min(40, Math.max(6, Math.ceil(fileCount / 25)));\n}\n\n/**\n * The deterministic half of the convention layer: partition the barrel-resolved\n * file graph into coarse areas and build each area's summarizer prompt and cache key.\n */\nexport function buildConventionAreas(\n store: CodeGraphStore,\n snapshotId: number,\n opts?: ConventionOptions,\n): ConventionCorpus {\n const nodes = store.listNodes(snapshotId, { includeSymbols: true });\n const { files, edges } = resolvedFileGraph(store, snapshotId, nodes);\n const symbolsByFile = collectExportedSymbols(nodes);\n const areas: ConventionArea[] = [];\n const prompts = new Map<string, string>();\n for (const members of partitionFiles(files, edges, opts)) {\n const { area, prompt } = buildArea(members, edges, symbolsByFile);\n areas.push(area);\n prompts.set(area.contentHash, prompt);\n }\n const grouped = areas.reduce((s, a) => s + a.size, 0);\n return { areas, prompts, coverage: { files: files.length, grouped, areas: areas.length, summarized: 0 } };\n}\n\nfunction resolvedFileGraph(\n store: CodeGraphStore,\n snapshotId: number,\n nodes: readonly GraphNode[],\n): { files: string[]; edges: GraphEdge[] } {\n const files = nodes\n .filter((n) => n.kind === \"file\" && n.role !== \"generated\")\n .map((n) => n.id)\n .sort();\n const fileSet = new Set(files);\n const edges = resolveBarrelEdges(nodes, store.listEdges(snapshotId)).filter(\n (e) => e.srcId !== e.dstId && fileSet.has(e.srcId) && fileSet.has(e.dstId),\n );\n return { files, edges };\n}\n\nfunction partitionFiles(files: readonly string[], edges: readonly GraphEdge[], opts?: ConventionOptions): string[][] {\n const target = opts?.targetCount ?? defaultTargetCount(files.length);\n const minSize = opts?.minSize ?? DEFAULT_MIN_SIZE;\n // A 2x cap on the ideal share keeps a dense repo from snowballing into one indescribable area.\n const maxSize = Math.max(minSize * 2, Math.ceil((files.length / target) * 2));\n return [...detectCommunities(files, edges, { targetCount: target, maxSize }).values()]\n .filter((members) => members.length >= minSize)\n .sort(bySizeThenFirstFile);\n}\n\nfunction bySizeThenFirstFile(a: string[], b: string[]): number {\n if (a.length !== b.length) return b.length - a.length;\n return (a[0] ?? \"\") < (b[0] ?? \"\") ? -1 : 1;\n}\n\ninterface SymbolAttrs {\n exported?: boolean;\n signature?: string;\n purpose?: string;\n}\n\nfunction collectExportedSymbols(nodes: readonly GraphNode[]): Map<string, ConventionSymbol[]> {\n const byFile = new Map<string, ConventionSymbol[]>();\n for (const n of nodes) {\n if (n.kind !== \"symbol\") continue;\n const attrs = (n.attrs ?? {}) as SymbolAttrs;\n if (attrs.exported !== true || !attrs.signature) continue;\n const file = n.parentId ?? n.id.split(\"#\")[0] ?? n.id;\n const list = byFile.get(file) ?? [];\n list.push({ name: n.name, signature: attrs.signature, purpose: attrs.purpose });\n byFile.set(file, list);\n }\n return byFile;\n}\n\nfunction buildArea(\n members: readonly string[],\n edges: readonly GraphEdge[],\n symbolsByFile: ReadonlyMap<string, ConventionSymbol[]>,\n): { area: ConventionArea; prompt: string } {\n const files = rankByDegree(members, edges);\n const label = dominantDirectory(files);\n const topSymbols = pickTopSymbols(files, symbolsByFile);\n const prompt = buildPrompt(label, files, topSymbols);\n const area: ConventionArea = {\n id: `area-${contentHashOf(files.join(\"\\n\")).slice(0, 8)}`,\n label,\n files,\n size: files.length,\n topSymbols,\n contentHash: contentHashOf(prompt),\n };\n return { area, prompt };\n}\n\nfunction rankByDegree(members: readonly string[], edges: readonly GraphEdge[]): string[] {\n const memberSet = new Set(members);\n const degree = new Map<string, number>();\n for (const e of edges) {\n if (!memberSet.has(e.srcId) || !memberSet.has(e.dstId)) continue;\n degree.set(e.srcId, (degree.get(e.srcId) ?? 0) + 1);\n degree.set(e.dstId, (degree.get(e.dstId) ?? 0) + 1);\n }\n return [...members].sort((a, b) => {\n const d = (degree.get(b) ?? 0) - (degree.get(a) ?? 0);\n return d !== 0 ? d : a < b ? -1 : 1;\n });\n}\n\nfunction dominantDirectory(files: readonly string[]): string {\n const counts = new Map<string, number>();\n for (const f of files) {\n const dir = path.posix.dirname(f);\n counts.set(dir, (counts.get(dir) ?? 0) + 1);\n }\n const dirs = [...counts.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1));\n const topDir = dirs[0]?.[0] ?? \".\";\n return dirs.length > 1 ? `${topDir} (+${dirs.length - 1} dirs)` : topDir;\n}\n\nfunction pickTopSymbols(\n rankedFiles: readonly string[],\n symbolsByFile: ReadonlyMap<string, ConventionSymbol[]>,\n): ConventionSymbol[] {\n const out: ConventionSymbol[] = [];\n for (const file of rankedFiles) {\n for (const sym of symbolsByFile.get(file) ?? []) {\n out.push(sym);\n if (out.length >= PROMPT_SYMBOL_CAP) return out;\n }\n }\n return out;\n}\n\nfunction buildPrompt(label: string, files: readonly string[], symbols: readonly ConventionSymbol[]): string {\n const shown = files.slice(0, PROMPT_FILE_CAP);\n const lines = [\n 'You are writing one entry of a repository \"convention map\" — a',\n \"capability-altitude summary coding agents read at PLAN time to learn how\",\n \"this repo does things and where new code belongs.\",\n \"\",\n `Capability area: ${label}`,\n `Files (${files.length}):`,\n ...shown.map((f) => `- ${f}`),\n ];\n if (files.length > shown.length) lines.push(`- …and ${files.length - shown.length} more`);\n if (symbols.length > 0) {\n lines.push(\"Key exported symbols:\");\n for (const s of symbols) lines.push(`- ${s.signature}${s.purpose ? ` — ${s.purpose}` : \"\"}`);\n }\n lines.push(\n \"\",\n \"Write 2-3 sentences: (1) what this area does, and (2) HOW — the key entry\",\n \"points, patterns and conventions to follow when adding related code.\",\n \"Plain text only, no preamble or headings.\",\n );\n return lines.join(\"\\n\");\n}\n","import { CacheBlobTable } from \"@titan-design/store-sqlite\";\nimport { KIT } from \"../schema.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { buildConventionAreas } from \"./areas.js\";\nimport type {\n ConventionArea,\n ConventionMap,\n ConventionOptions,\n SummarizeConventionsResult,\n Summarizer,\n} from \"./types.js\";\n\n/** The blob_cache namespace for area summaries; the model column holds `summarizer.model`. */\nexport const COMMUNITY_SUMMARY_NAMESPACE = \"code-graph/community-summary\";\n\nfunction summaryCache(store: CodeGraphStore): CacheBlobTable {\n return new CacheBlobTable(store.db, { name: KIT.cacheBlob });\n}\n\nfunction loadSummaries(store: CodeGraphStore, model: string, hashes: readonly string[]): Map<string, string> {\n const cache = summaryCache(store);\n const found = new Map<string, string>();\n for (const contentHash of new Set(hashes)) {\n const hit = cache.get({ namespace: COMMUNITY_SUMMARY_NAMESPACE, model, contentHash });\n if (hit) found.set(contentHash, hit.value.toString(\"utf8\"));\n }\n return found;\n}\n\nfunction storeSummary(store: CodeGraphStore, model: string, contentHash: string, summary: string): void {\n summaryCache(store).put({ namespace: COMMUNITY_SUMMARY_NAMESPACE, model, contentHash }, summary);\n}\n\nfunction attachSummaries(areas: ConventionArea[], summaries: ReadonlyMap<string, string>): void {\n for (const area of areas) area.summary = summaries.get(area.contentHash);\n}\n\n/**\n * Generate or reuse the summary of every area. Only cache misses reach the\n * summarizer, so cost scales with what structurally changed, not with repo size.\n */\nexport async function summarizeConventions(\n store: CodeGraphStore,\n snapshotId: number,\n summarizer: Summarizer,\n opts?: ConventionOptions,\n): Promise<SummarizeConventionsResult> {\n const { areas, prompts, coverage } = buildConventionAreas(store, snapshotId, opts);\n attachSummaries(areas, loadSummaries(store, summarizer.model, areas.map((a) => a.contentHash)));\n let newlySummarized = 0;\n for (const area of areas) {\n if (area.summary !== undefined) continue;\n const summary = (await summarizer.summarize(prompts.get(area.contentHash)!)).trim();\n storeSummary(store, summarizer.model, area.contentHash, summary);\n area.summary = summary;\n newlySummarized++;\n }\n coverage.summarized = areas.filter((a) => a.summary).length;\n return { model: summarizer.model, coverage, areas, newlySummarized, reused: areas.length - newlySummarized };\n}\n\n/** Read-only view: the partition plus whatever summaries are already stored. Never calls a summarizer. */\nexport function getConventionMap(\n store: CodeGraphStore,\n snapshotId: number,\n model: string,\n opts?: ConventionOptions,\n): ConventionMap {\n const { areas, coverage } = buildConventionAreas(store, snapshotId, opts);\n attachSummaries(areas, loadSummaries(store, model, areas.map((a) => a.contentHash)));\n coverage.summarized = areas.filter((a) => a.summary).length;\n return { model, coverage, areas };\n}\n","import type { Embedder } from \"@titan-design/embed\";\nimport { BruteForceVectorIndex, vectorRetriever } from \"@titan-design/retrieval\";\nimport { embedTextsCached } from \"../embeddings/cache.js\";\nimport { hashEmbedText } from \"../embeddings/corpus.js\";\nimport type { CodeGraphStore } from \"../store.js\";\nimport { getConventionMap } from \"./summaries.js\";\nimport type { ConventionArea, ConventionMatch, ConventionQueryResult, FindConventionsOptions } from \"./types.js\";\n\nconst MATCH_FILE_CAP = 5;\nconst DEFAULT_LIMIT = 3;\n\n/**\n * \"How does this repo do X?\": rank summarized areas by similarity of their\n * summary to the question. Returns candidates, not verdicts. Summary vectors\n * share the content-addressed embedding cache with the symbol layer.\n */\nexport async function findConventions(\n store: CodeGraphStore,\n snapshotId: number,\n query: string,\n embedder: Embedder,\n model: string,\n opts: FindConventionsOptions = {},\n): Promise<ConventionQueryResult> {\n const map = getConventionMap(store, snapshotId, model, opts);\n const summarized = map.areas.filter((a): a is ConventionArea & { summary: string } => Boolean(a.summary));\n if (summarized.length === 0) {\n throw new Error(`No convention summaries stored for model ${model}; run summarizeConventions first.`);\n }\n const { byHash } = await embedTextsCached(store, embedder, summarized.map((a) => a.summary));\n const index = new BruteForceVectorIndex();\n for (const area of summarized) index.add(area.id, byHash.get(hashEmbedText(area.summary))!);\n const hits = await vectorRetriever(embedder, index).retrieve(query, { limit: opts.limit ?? DEFAULT_LIMIT });\n const byId = new Map(summarized.map((a) => [a.id, a]));\n return {\n query,\n model,\n embeddingModel: embedder.model,\n coverage: map.coverage,\n matches: hits.map((h) => toMatch(byId.get(h.id)!, h.score ?? 0)),\n };\n}\n\nfunction toMatch(area: ConventionArea & { summary: string }, score: number): ConventionMatch {\n return {\n id: area.id,\n label: area.label,\n summary: area.summary,\n files: area.files.slice(0, MATCH_FILE_CAP),\n size: area.size,\n score,\n };\n}\n"],"mappings":"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","names":["edge","realpathSync","path","Project","relative","path","path","step","Node","Node","bindingName","Node","scopeSegment","Node","fileId","Node","SyntaxKind","SyntaxKind","Node","targetFileId","path","fs","relative","fs","Node","SyntaxKind","Node","SyntaxKind","fileId","symbolNodes","Project","path","fileId","resolve","resolveCallee","literalText","path","path","candidates","fileId","path","path","path","isExcludedDir","shouldIncludeFile","Project","Project","isExcludedDir","shouldIncludeFile","edge","resolve","getLanguageFromPath","fileId","fileId","fileIdOf","symbolNamesByFile","RECEIVERS","walk","TERMINALS","fileIdOf","unreachableInBlock","analyzeFunction","countReferences","ownParamNames","walk","fileIdOf","fileId","edge","getLanguageFromPath","edge","removed","edge","edge","fileId","realpathSync","getLanguageFromPath","parseFile","shouldIncludeFile","readFileSync","path","Node","Project","ScriptTarget","readFileSync","Project","ScriptTarget","Node","oneLine","fileIdOf","fileId","parseFile","parseFile","compare","SCHEMA_VERSION","symbolId","fileId","path","readFileSync","path","targetFileId","fileId","readFileSync","fileId","symbolNodes","edge","edge","toViolation","createHash","snap","path","edgeKey","removed","signatureOf","resolve","compare","missing","path","contentHashOf","contentHashOf","CacheBlobTable","CacheBlobTable","BruteForceVectorIndex","vectorRetriever","BruteForceVectorIndex","vectorRetriever"]}