@seanhogg/builderforce-memory 2026.10.27 → 2026.10.29
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/ingest/IngestionPipeline.d.ts +1 -8
- package/dist/ingest/IngestionPipeline.d.ts.map +1 -1
- package/dist/ingest/IngestionPipeline.js +3 -15
- package/dist/ingest/IngestionPipeline.js.map +1 -1
- package/dist/ingest/docsExtract.d.ts +30 -0
- package/dist/ingest/docsExtract.d.ts.map +1 -0
- package/dist/ingest/docsExtract.js +221 -0
- package/dist/ingest/docsExtract.js.map +1 -0
- package/dist/ingest/hash.d.ts +15 -0
- package/dist/ingest/hash.d.ts.map +1 -0
- package/dist/ingest/hash.js +22 -0
- package/dist/ingest/hash.js.map +1 -0
- package/dist/ingest/parsers.d.ts.map +1 -1
- package/dist/ingest/parsers.js +4 -0
- package/dist/ingest/parsers.js.map +1 -1
- package/dist/ingest/types.d.ts +7 -0
- package/dist/ingest/types.d.ts.map +1 -1
- package/dist/ingest/types.js.map +1 -1
- package/dist/knowledge/build.d.ts +24 -0
- package/dist/knowledge/build.d.ts.map +1 -0
- package/dist/knowledge/build.js +263 -0
- package/dist/knowledge/build.js.map +1 -0
- package/dist/knowledge/cards.d.ts +17 -0
- package/dist/knowledge/cards.d.ts.map +1 -0
- package/dist/knowledge/cards.js +118 -0
- package/dist/knowledge/cards.js.map +1 -0
- package/dist/knowledge/findings.d.ts +24 -0
- package/dist/knowledge/findings.d.ts.map +1 -0
- package/dist/knowledge/findings.js +152 -0
- package/dist/knowledge/findings.js.map +1 -0
- package/dist/knowledge/importance.d.ts +21 -0
- package/dist/knowledge/importance.d.ts.map +1 -0
- package/dist/knowledge/importance.js +70 -0
- package/dist/knowledge/importance.js.map +1 -0
- package/dist/knowledge/index.d.ts +31 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +26 -0
- package/dist/knowledge/index.js.map +1 -0
- package/dist/knowledge/judge.d.ts +86 -0
- package/dist/knowledge/judge.d.ts.map +1 -0
- package/dist/knowledge/judge.js +213 -0
- package/dist/knowledge/judge.js.map +1 -0
- package/dist/knowledge/model.d.ts +333 -0
- package/dist/knowledge/model.d.ts.map +1 -0
- package/dist/knowledge/model.js +13 -0
- package/dist/knowledge/model.js.map +1 -0
- package/dist/knowledge/packs/docs.d.ts +17 -0
- package/dist/knowledge/packs/docs.d.ts.map +1 -0
- package/dist/knowledge/packs/docs.js +89 -0
- package/dist/knowledge/packs/docs.js.map +1 -0
- package/dist/knowledge/partitions.d.ts +31 -0
- package/dist/knowledge/partitions.d.ts.map +1 -0
- package/dist/knowledge/partitions.js +135 -0
- package/dist/knowledge/partitions.js.map +1 -0
- package/dist/knowledge/plan.d.ts +33 -0
- package/dist/knowledge/plan.d.ts.map +1 -0
- package/dist/knowledge/plan.js +89 -0
- package/dist/knowledge/plan.js.map +1 -0
- package/dist/knowledge/refs.d.ts +40 -0
- package/dist/knowledge/refs.d.ts.map +1 -0
- package/dist/knowledge/refs.js +102 -0
- package/dist/knowledge/refs.js.map +1 -0
- package/dist/knowledge/resolve.d.ts +35 -0
- package/dist/knowledge/resolve.d.ts.map +1 -0
- package/dist/knowledge/resolve.js +67 -0
- package/dist/knowledge/resolve.js.map +1 -0
- package/dist/knowledge/review.d.ts +23 -0
- package/dist/knowledge/review.d.ts.map +1 -0
- package/dist/knowledge/review.js +233 -0
- package/dist/knowledge/review.js.map +1 -0
- package/dist/knowledge/sources.d.ts +47 -0
- package/dist/knowledge/sources.d.ts.map +1 -0
- package/dist/knowledge/sources.js +136 -0
- package/dist/knowledge/sources.js.map +1 -0
- package/dist/knowledge/stores/localSnapshotStore.d.ts +50 -0
- package/dist/knowledge/stores/localSnapshotStore.d.ts.map +1 -0
- package/dist/knowledge/stores/localSnapshotStore.js +125 -0
- package/dist/knowledge/stores/localSnapshotStore.js.map +1 -0
- package/dist/knowledge/trace.d.ts +32 -0
- package/dist/knowledge/trace.d.ts.map +1 -0
- package/dist/knowledge/trace.js +102 -0
- package/dist/knowledge/trace.js.map +1 -0
- package/dist/knowledge/truncate.d.ts +24 -0
- package/dist/knowledge/truncate.d.ts.map +1 -0
- package/dist/knowledge/truncate.js +128 -0
- package/dist/knowledge/truncate.js.map +1 -0
- package/dist/memory/SemanticRecall.d.ts.map +1 -1
- package/dist/memory/SemanticRecall.js +3 -1
- package/dist/memory/SemanticRecall.js.map +1 -1
- package/dist/retrieval/HybridRetriever.d.ts.map +1 -1
- package/dist/retrieval/HybridRetriever.js +3 -1
- package/dist/retrieval/HybridRetriever.js.map +1 -1
- package/dist/retrieval/bm25.d.ts +3 -2
- package/dist/retrieval/bm25.d.ts.map +1 -1
- package/dist/retrieval/bm25.js +5 -3
- package/dist/retrieval/bm25.js.map +1 -1
- package/dist/retrieval/fusion.d.ts +2 -1
- package/dist/retrieval/fusion.d.ts.map +1 -1
- package/dist/retrieval/fusion.js +4 -2
- package/dist/retrieval/fusion.js.map +1 -1
- package/dist/retrieval/hnsw.d.ts +49 -11
- package/dist/retrieval/hnsw.d.ts.map +1 -1
- package/dist/retrieval/hnsw.js +57 -29
- package/dist/retrieval/hnsw.js.map +1 -1
- package/dist/retrieval/index.d.ts +7 -3
- package/dist/retrieval/index.d.ts.map +1 -1
- package/dist/retrieval/index.js +5 -2
- package/dist/retrieval/index.js.map +1 -1
- package/dist/retrieval/knowledge-index/bytes.d.ts +43 -0
- package/dist/retrieval/knowledge-index/bytes.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/bytes.js +151 -0
- package/dist/retrieval/knowledge-index/bytes.js.map +1 -0
- package/dist/retrieval/knowledge-index/cascade.d.ts +37 -0
- package/dist/retrieval/knowledge-index/cascade.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/cascade.js +111 -0
- package/dist/retrieval/knowledge-index/cascade.js.map +1 -0
- package/dist/retrieval/knowledge-index/compact.d.ts +18 -0
- package/dist/retrieval/knowledge-index/compact.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/compact.js +64 -0
- package/dist/retrieval/knowledge-index/compact.js.map +1 -0
- package/dist/retrieval/knowledge-index/csr.d.ts +41 -0
- package/dist/retrieval/knowledge-index/csr.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/csr.js +76 -0
- package/dist/retrieval/knowledge-index/csr.js.map +1 -0
- package/dist/retrieval/knowledge-index/digest.d.ts +21 -0
- package/dist/retrieval/knowledge-index/digest.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/digest.js +50 -0
- package/dist/retrieval/knowledge-index/digest.js.map +1 -0
- package/dist/retrieval/knowledge-index/embeddings.d.ts +32 -0
- package/dist/retrieval/knowledge-index/embeddings.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/embeddings.js +78 -0
- package/dist/retrieval/knowledge-index/embeddings.js.map +1 -0
- package/dist/retrieval/knowledge-index/expand.d.ts +19 -0
- package/dist/retrieval/knowledge-index/expand.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/expand.js +49 -0
- package/dist/retrieval/knowledge-index/expand.js.map +1 -0
- package/dist/retrieval/knowledge-index/index.d.ts +40 -0
- package/dist/retrieval/knowledge-index/index.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/index.js +134 -0
- package/dist/retrieval/knowledge-index/index.js.map +1 -0
- package/dist/retrieval/knowledge-index/lexical.d.ts +26 -0
- package/dist/retrieval/knowledge-index/lexical.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/lexical.js +76 -0
- package/dist/retrieval/knowledge-index/lexical.js.map +1 -0
- package/dist/retrieval/knowledge-index/pairs.d.ts +22 -0
- package/dist/retrieval/knowledge-index/pairs.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/pairs.js +51 -0
- package/dist/retrieval/knowledge-index/pairs.js.map +1 -0
- package/dist/retrieval/knowledge-index/prune.d.ts +21 -0
- package/dist/retrieval/knowledge-index/prune.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/prune.js +43 -0
- package/dist/retrieval/knowledge-index/prune.js.map +1 -0
- package/dist/retrieval/knowledge-index/quantize.d.ts +37 -0
- package/dist/retrieval/knowledge-index/quantize.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/quantize.js +77 -0
- package/dist/retrieval/knowledge-index/quantize.js.map +1 -0
- package/dist/retrieval/knowledge-index/serialize.d.ts +18 -0
- package/dist/retrieval/knowledge-index/serialize.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/serialize.js +123 -0
- package/dist/retrieval/knowledge-index/serialize.js.map +1 -0
- package/dist/retrieval/knowledge-index/sha256.d.ts +30 -0
- package/dist/retrieval/knowledge-index/sha256.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/sha256.js +130 -0
- package/dist/retrieval/knowledge-index/sha256.js.map +1 -0
- package/dist/retrieval/knowledge-index/state.d.ts +55 -0
- package/dist/retrieval/knowledge-index/state.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/state.js +67 -0
- package/dist/retrieval/knowledge-index/state.js.map +1 -0
- package/dist/retrieval/knowledge-index/tokenize.d.ts +20 -0
- package/dist/retrieval/knowledge-index/tokenize.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/tokenize.js +42 -0
- package/dist/retrieval/knowledge-index/tokenize.js.map +1 -0
- package/dist/retrieval/knowledge-index/traverse.d.ts +26 -0
- package/dist/retrieval/knowledge-index/traverse.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/traverse.js +90 -0
- package/dist/retrieval/knowledge-index/traverse.js.map +1 -0
- package/dist/retrieval/knowledge-index/types.d.ts +85 -0
- package/dist/retrieval/knowledge-index/types.d.ts.map +1 -0
- package/dist/retrieval/knowledge-index/types.js +9 -0
- package/dist/retrieval/knowledge-index/types.js.map +1 -0
- package/dist/retrieval/mmr.d.ts +11 -4
- package/dist/retrieval/mmr.d.ts.map +1 -1
- package/dist/retrieval/mmr.js +28 -8
- package/dist/retrieval/mmr.js.map +1 -1
- package/dist/retrieval/order.d.ts +41 -0
- package/dist/retrieval/order.d.ts.map +1 -0
- package/dist/retrieval/order.js +54 -0
- package/dist/retrieval/order.js.map +1 -0
- package/dist/retrieval/weightedFusion.d.ts +2 -1
- package/dist/retrieval/weightedFusion.d.ts.map +1 -1
- package/dist/retrieval/weightedFusion.js +7 -5
- package/dist/retrieval/weightedFusion.js.map +1 -1
- package/dist/vectorstore/MemoryVectorStore.d.ts.map +1 -1
- package/dist/vectorstore/MemoryVectorStore.js +2 -1
- package/dist/vectorstore/MemoryVectorStore.js.map +1 -1
- package/package.json +16 -5
- package/src/ingest/IngestionPipeline.ts +3 -15
- package/src/ingest/docsExtract.ts +219 -0
- package/src/ingest/hash.ts +22 -0
- package/src/ingest/parsers.ts +4 -0
- package/src/ingest/types.ts +7 -0
- package/src/knowledge/build.test.ts +150 -0
- package/src/knowledge/build.ts +266 -0
- package/src/knowledge/cards.ts +130 -0
- package/src/knowledge/docs.test.ts +118 -0
- package/src/knowledge/findings.ts +159 -0
- package/src/knowledge/importance.ts +72 -0
- package/src/knowledge/index.ts +53 -0
- package/src/knowledge/judge.ts +231 -0
- package/src/knowledge/model.ts +312 -0
- package/src/knowledge/packs/docs.ts +91 -0
- package/src/knowledge/partitions.test.ts +98 -0
- package/src/knowledge/partitions.ts +119 -0
- package/src/knowledge/plan.ts +115 -0
- package/src/knowledge/refs.ts +108 -0
- package/src/knowledge/resolve.ts +78 -0
- package/src/knowledge/review.test.ts +180 -0
- package/src/knowledge/review.ts +235 -0
- package/src/knowledge/sources.ts +146 -0
- package/src/knowledge/stores/localSnapshotStore.test.ts +82 -0
- package/src/knowledge/stores/localSnapshotStore.ts +159 -0
- package/src/knowledge/testkit.test-util.ts +92 -0
- package/src/knowledge/trace.test.ts +91 -0
- package/src/knowledge/trace.ts +111 -0
- package/src/knowledge/truncate.ts +118 -0
- package/src/memory/SemanticRecall.ts +3 -1
- package/src/retrieval/HybridRetriever.ts +3 -1
- package/src/retrieval/bm25.ts +5 -3
- package/src/retrieval/fusion.ts +5 -2
- package/src/retrieval/hnsw.ts +82 -35
- package/src/retrieval/index.ts +17 -3
- package/src/retrieval/knowledge-index/bytes.ts +166 -0
- package/src/retrieval/knowledge-index/cascade.ts +125 -0
- package/src/retrieval/knowledge-index/compact.ts +68 -0
- package/src/retrieval/knowledge-index/csr.ts +102 -0
- package/src/retrieval/knowledge-index/digest.ts +54 -0
- package/src/retrieval/knowledge-index/embeddings.ts +85 -0
- package/src/retrieval/knowledge-index/expand.ts +55 -0
- package/src/retrieval/knowledge-index/index.ts +162 -0
- package/src/retrieval/knowledge-index/lexical.ts +78 -0
- package/src/retrieval/knowledge-index/pairs.ts +57 -0
- package/src/retrieval/knowledge-index/prune.ts +48 -0
- package/src/retrieval/knowledge-index/quantize.ts +78 -0
- package/src/retrieval/knowledge-index/serialize.ts +124 -0
- package/src/retrieval/knowledge-index/sha256.ts +122 -0
- package/src/retrieval/knowledge-index/state.ts +108 -0
- package/src/retrieval/knowledge-index/tokenize.ts +41 -0
- package/src/retrieval/knowledge-index/traverse.ts +95 -0
- package/src/retrieval/knowledge-index/types.ts +78 -0
- package/src/retrieval/mmr.ts +35 -10
- package/src/retrieval/order.ts +68 -0
- package/src/retrieval/weightedFusion.ts +8 -5
- package/src/vectorstore/MemoryVectorStore.ts +2 -1
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* knowledge/build.ts — `buildGraph`: join perception (extracted, computed) with memory
|
|
3
|
+
* (stored facts and relations) into one bounded {@link KnowledgeGraph} (PRD 38 §4.1).
|
|
4
|
+
*
|
|
5
|
+
* 1. extracted nodes/edges (analyzer output merges its badges into the same refs);
|
|
6
|
+
* 2. facts become nodes, joined to sources by `fileAnchors.path`; a model fact whose
|
|
7
|
+
* anchor hash differs from the source's current hash is `stale`;
|
|
8
|
+
* 3. stored relations become edges; near-duplicate pairs become `near-duplicate` edges
|
|
9
|
+
* (an exact `duplicate` between the same pair wins); live changes badge nodes and
|
|
10
|
+
* `runFiles` become `co-changed` edges;
|
|
11
|
+
* 4. partitions, areas, verdicts; PageRank importance; findings; then truncation.
|
|
12
|
+
*
|
|
13
|
+
* Deterministic: equal input ⇒ byte-identical JSON. Every list is sorted, every sort ends
|
|
14
|
+
* on ref, objects are built with a fixed key order.
|
|
15
|
+
*/
|
|
16
|
+
import { areaOfPath } from '../working/codemapAreas.js';
|
|
17
|
+
import { sha256Hex } from '../retrieval/knowledge-index/sha256.js';
|
|
18
|
+
import { computeFindings } from './findings.js';
|
|
19
|
+
import { pageRank } from './importance.js';
|
|
20
|
+
import { loadPartitions, partitionOf, verdictOf } from './partitions.js';
|
|
21
|
+
import { entityName } from './resolve.js';
|
|
22
|
+
import { basenameOf, canonicalJson, compareStr, factRef, pathOfRef, round6, sortBy, srcRef, } from './refs.js';
|
|
23
|
+
import { truncateGraph } from './truncate.js';
|
|
24
|
+
export const DEFAULT_MAX_NODES = 400;
|
|
25
|
+
export const MAX_NODES_CAP = 2000;
|
|
26
|
+
const LABEL_CHARS = 120;
|
|
27
|
+
const edgeId = (from, to, kind) => `${from}\u0000${to}\u0000${kind}`;
|
|
28
|
+
export const compareEdges = (a, b) => compareStr(a.from, b.from) || compareStr(a.to, b.to) || compareStr(a.kind, b.kind);
|
|
29
|
+
/** sha-256 over the canonical input: equal inputs (in any order) ⇒ equal digests. */
|
|
30
|
+
export function graphDigest(input) {
|
|
31
|
+
return sha256Hex(canonicalJson({
|
|
32
|
+
rootId: input.rootId,
|
|
33
|
+
packs: input.packs.map((p) => p.id).sort(compareStr),
|
|
34
|
+
extracted: sortBy(input.extracted, (e) => e.sourceRef, (e) => e.sourceHash).map(canonicalExtracted),
|
|
35
|
+
facts: sortBy(input.facts, (f) => f.key).map((f) => ({ ...f, fileAnchors: sortBy(f.fileAnchors, (a) => a.path) })),
|
|
36
|
+
relations: sortBy(input.relations, (r) => r.from, (r) => r.to, (r) => r.kind),
|
|
37
|
+
live: input.live && {
|
|
38
|
+
changes: sortBy(input.live.changes, (c) => c.path),
|
|
39
|
+
runFiles: nonEmpty(input.live.runFiles) && [...input.live.runFiles].sort(compareStr),
|
|
40
|
+
},
|
|
41
|
+
nearDuplicates: nonEmpty(input.nearDuplicates) && sortBy(input.nearDuplicates, (p) => p.a, (p) => p.b),
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
/** An absent list and an empty list mean the same input, so they hash the same. */
|
|
45
|
+
const nonEmpty = (xs) => (xs && xs.length > 0) || undefined;
|
|
46
|
+
function canonicalExtracted(e) {
|
|
47
|
+
return {
|
|
48
|
+
sourceRef: e.sourceRef, sourceHash: e.sourceHash,
|
|
49
|
+
nodes: sortBy(e.nodes, (n) => n.ref),
|
|
50
|
+
edges: [...e.edges].sort(compareEdges),
|
|
51
|
+
keys: sortBy(e.keys, (k) => k.ref, (k) => k.key),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function mergeBadges(a, b) {
|
|
55
|
+
if (!a)
|
|
56
|
+
return b && { ...b };
|
|
57
|
+
if (!b)
|
|
58
|
+
return { ...a };
|
|
59
|
+
const out = { ...a };
|
|
60
|
+
// Commutative: on a conflict the larger value (as a string) wins, whatever the order.
|
|
61
|
+
for (const [k, v] of Object.entries(b))
|
|
62
|
+
out[k] = k in out && String(out[k]) >= String(v) ? out[k] : v;
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
function oneLine(text) {
|
|
66
|
+
const flat = text.replace(/\s+/g, ' ').trim();
|
|
67
|
+
return flat.length > LABEL_CHARS ? `${flat.slice(0, LABEL_CHARS - 1)}…` : flat;
|
|
68
|
+
}
|
|
69
|
+
class GraphBuilder {
|
|
70
|
+
nodes = new Map();
|
|
71
|
+
edges = new Map();
|
|
72
|
+
node(n) {
|
|
73
|
+
const prior = this.nodes.get(n.ref);
|
|
74
|
+
if (!prior) {
|
|
75
|
+
this.nodes.set(n.ref, { ...n, ...(n.badges ? { badges: { ...n.badges } } : {}) });
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const badges = mergeBadges(prior.badges, n.badges);
|
|
79
|
+
if (badges)
|
|
80
|
+
prior.badges = badges;
|
|
81
|
+
}
|
|
82
|
+
edge(e) {
|
|
83
|
+
const id = edgeId(e.from, e.to, e.kind);
|
|
84
|
+
const prior = this.edges.get(id);
|
|
85
|
+
if (!prior) {
|
|
86
|
+
this.edges.set(id, { ...e });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
prior.weight = Math.max(prior.weight, e.weight);
|
|
90
|
+
if (e.cycle)
|
|
91
|
+
prior.cycle = true;
|
|
92
|
+
if (e.confidence !== undefined)
|
|
93
|
+
prior.confidence = Math.max(prior.confidence ?? 0, e.confidence);
|
|
94
|
+
}
|
|
95
|
+
has(from, to, kind) {
|
|
96
|
+
return this.edges.has(edgeId(from, to, kind));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function factNode(f, rootId, g) {
|
|
100
|
+
const ref = factRef(f.key);
|
|
101
|
+
const kind = f.key.startsWith('ent:') ? 'entity' : f.key.startsWith('claim:') ? 'claim' : 'fact';
|
|
102
|
+
const anchors = sortBy(f.fileAnchors, (a) => a.path);
|
|
103
|
+
const anchoredPack = anchors.map((a) => g.nodes.get(srcRef(rootId, a.path))?.pack).find(Boolean);
|
|
104
|
+
const pack = kind === 'entity' ? f.key.split(':')[1] || 'memory' : anchoredPack ?? 'memory';
|
|
105
|
+
const stale = f.origin === 'model' && anchors.some((a) => {
|
|
106
|
+
const current = g.nodes.get(srcRef(rootId, a.path))?.sourceHash;
|
|
107
|
+
return !!a.contentHash && !!current && current !== a.contentHash;
|
|
108
|
+
});
|
|
109
|
+
const first = anchors[0];
|
|
110
|
+
return {
|
|
111
|
+
ref, kind, label: oneLine(kind === 'entity' ? f.content || entityName(ref) : f.content), pack,
|
|
112
|
+
importance: 0, origin: f.origin,
|
|
113
|
+
...(first?.contentHash ? { sourceHash: first.contentHash } : {}),
|
|
114
|
+
...(stale ? { stale: true } : {}),
|
|
115
|
+
...(first?.line !== undefined ? { badges: { line: first.line } } : {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
export function buildGraph(input, opts = {}) {
|
|
119
|
+
const { rootId } = input;
|
|
120
|
+
const g = new GraphBuilder();
|
|
121
|
+
const sources = new Set();
|
|
122
|
+
for (const ex of sortBy(input.extracted, (e) => e.sourceRef, (e) => e.sourceHash)) {
|
|
123
|
+
if (ex.sourceRef.startsWith('src:'))
|
|
124
|
+
sources.add(ex.sourceRef);
|
|
125
|
+
for (const n of sortBy(ex.nodes, (x) => x.ref))
|
|
126
|
+
g.node({ ...n, origin: 'extracted' });
|
|
127
|
+
for (const e of [...ex.edges].sort(compareEdges))
|
|
128
|
+
g.edge({ ...e, origin: 'extracted' });
|
|
129
|
+
}
|
|
130
|
+
const facts = sortBy(input.facts, (f) => f.key);
|
|
131
|
+
for (const f of facts)
|
|
132
|
+
g.node(factNode(f, rootId, g));
|
|
133
|
+
for (const f of facts) {
|
|
134
|
+
for (const a of sortBy(f.fileAnchors, (x) => x.path)) {
|
|
135
|
+
const to = srcRef(rootId, a.path);
|
|
136
|
+
if (g.nodes.has(to))
|
|
137
|
+
g.edge({ from: factRef(f.key), to, kind: 'about', weight: 1, origin: f.origin });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
for (const r of sortBy(input.relations, (x) => x.from, (x) => x.to, (x) => x.kind)) {
|
|
141
|
+
g.edge({
|
|
142
|
+
from: r.from, to: r.to, kind: r.kind, weight: r.weight, origin: r.origin,
|
|
143
|
+
...(r.confidence !== undefined ? { confidence: r.confidence } : {}),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
for (const p of sortBy(input.nearDuplicates ?? [], (x) => x.a, (x) => x.b)) {
|
|
147
|
+
if (p.a === p.b || p.a.startsWith('ent:') || p.b.startsWith('ent:'))
|
|
148
|
+
continue;
|
|
149
|
+
const [a, b] = (compareStr(p.a, p.b) < 0 ? [p.a, p.b] : [p.b, p.a]);
|
|
150
|
+
if (!g.nodes.has(a) || !g.nodes.has(b) || g.has(a, b, 'duplicate') || g.has(b, a, 'duplicate'))
|
|
151
|
+
continue;
|
|
152
|
+
g.edge({ from: a, to: b, kind: 'near-duplicate', weight: round6(p.similarity), origin: 'extracted' });
|
|
153
|
+
}
|
|
154
|
+
const changed = applyLive(input, g);
|
|
155
|
+
closeEndpoints(g);
|
|
156
|
+
const registries = new Map(input.packs.map((p) => [p.id, loadPartitions(p)]));
|
|
157
|
+
placeNodes(rootId, g, registries);
|
|
158
|
+
const rank = pageRank([...g.nodes.keys()], [...g.edges.values()]);
|
|
159
|
+
for (const n of g.nodes.values())
|
|
160
|
+
n.importance = rank.get(n.ref) ?? 0;
|
|
161
|
+
const allNodes = [...g.nodes.values()].map(finalNode).sort((a, b) => compareStr(a.ref, b.ref));
|
|
162
|
+
const allEdges = [...g.edges.values()].map(finalEdge).sort(compareEdges);
|
|
163
|
+
const packs = input.packs.map((p) => p.id).sort(compareStr);
|
|
164
|
+
const full = {
|
|
165
|
+
scope: { rootId, packs, digest: graphDigest(input) },
|
|
166
|
+
nodes: allNodes, edges: allEdges, findings: [],
|
|
167
|
+
stats: { sources: sources.size, nodes: allNodes.length, edges: allEdges.length, stale: 0, truncated: false },
|
|
168
|
+
};
|
|
169
|
+
full.findings = computeFindings(full, input.packs, registries, input.nearDuplicates ?? []);
|
|
170
|
+
full.stats.stale = allNodes.filter((n) => n.stale).length;
|
|
171
|
+
const maxNodes = Math.min(MAX_NODES_CAP, Math.max(1, Math.floor(opts.maxNodes ?? DEFAULT_MAX_NODES)));
|
|
172
|
+
const cut = truncateGraph(full, { maxNodes, focus: opts.focus ?? [], changed });
|
|
173
|
+
return {
|
|
174
|
+
...full,
|
|
175
|
+
nodes: cut.nodes,
|
|
176
|
+
edges: cut.edges,
|
|
177
|
+
stats: { ...full.stats, nodes: cut.nodes.length, edges: cut.edges.length, truncated: cut.truncated },
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function applyLive(input, g) {
|
|
181
|
+
const changed = [];
|
|
182
|
+
if (!input.live)
|
|
183
|
+
return changed;
|
|
184
|
+
for (const c of sortBy(input.live.changes, (x) => x.path)) {
|
|
185
|
+
const ref = srcRef(input.rootId, c.path);
|
|
186
|
+
if (!g.nodes.has(ref))
|
|
187
|
+
continue;
|
|
188
|
+
g.node({ ...g.nodes.get(ref), badges: { added: c.added, removed: c.removed, status: c.status } });
|
|
189
|
+
changed.push(ref);
|
|
190
|
+
}
|
|
191
|
+
const run = [...new Set(input.live.runFiles ?? [])].sort(compareStr)
|
|
192
|
+
.map((p) => srcRef(input.rootId, p)).filter((r) => g.nodes.has(r));
|
|
193
|
+
for (let i = 0; i < run.length; i++) {
|
|
194
|
+
for (let j = i + 1; j < run.length; j++) {
|
|
195
|
+
g.edge({ from: run[i], to: run[j], kind: 'co-changed', weight: 1, origin: 'agent' });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return changed;
|
|
199
|
+
}
|
|
200
|
+
/** A missing `src:` endpoint becomes a `missing` placeholder (a broken link); a missing fact drops the edge. */
|
|
201
|
+
function closeEndpoints(g) {
|
|
202
|
+
for (const [id, e] of [...g.edges.entries()].sort((a, b) => compareStr(a[0], b[0]))) {
|
|
203
|
+
const ends = [e.from, e.to].filter((end) => !g.nodes.has(end));
|
|
204
|
+
if (ends.some((end) => pathOfRef(end) === undefined)) {
|
|
205
|
+
g.edges.delete(id);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
for (const end of ends) {
|
|
209
|
+
const path = pathOfRef(end);
|
|
210
|
+
const other = g.nodes.get(end === e.from ? e.to : e.from);
|
|
211
|
+
g.node({
|
|
212
|
+
ref: end, kind: 'missing', label: basenameOf(path) || path, pack: other?.pack ?? 'memory',
|
|
213
|
+
importance: 0, origin: 'extracted', badges: { missing: 1 },
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function placeNodes(rootId, g, registries) {
|
|
219
|
+
for (const n of g.nodes.values()) {
|
|
220
|
+
const path = pathOfRef(n.ref);
|
|
221
|
+
if (path === undefined)
|
|
222
|
+
continue;
|
|
223
|
+
const reg = registries.get(n.pack);
|
|
224
|
+
const partition = reg ? partitionOf(path, reg) : undefined;
|
|
225
|
+
if (partition !== undefined)
|
|
226
|
+
n.partition = partition;
|
|
227
|
+
const area = areaOfPath(path);
|
|
228
|
+
if (area)
|
|
229
|
+
n.area = srcRef(rootId, area);
|
|
230
|
+
}
|
|
231
|
+
for (const e of g.edges.values()) {
|
|
232
|
+
const from = g.nodes.get(e.from), to = g.nodes.get(e.to);
|
|
233
|
+
const reg = from && registries.get(from.pack);
|
|
234
|
+
if (!from || !to || !reg || from.pack !== to.pack)
|
|
235
|
+
continue;
|
|
236
|
+
const verdict = verdictOf(from.partition, to.partition, reg);
|
|
237
|
+
if (verdict)
|
|
238
|
+
e.verdict = verdict;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function finalNode(n) {
|
|
242
|
+
const badges = n.badges && Object.keys(n.badges).length
|
|
243
|
+
? Object.fromEntries(Object.keys(n.badges).sort(compareStr).map((k) => [k, n.badges[k]]))
|
|
244
|
+
: undefined;
|
|
245
|
+
return {
|
|
246
|
+
ref: n.ref, kind: n.kind, label: n.label, pack: n.pack,
|
|
247
|
+
...(n.partition !== undefined ? { partition: n.partition } : {}),
|
|
248
|
+
...(n.area !== undefined ? { area: n.area } : {}),
|
|
249
|
+
importance: n.importance, origin: n.origin,
|
|
250
|
+
...(n.sourceHash !== undefined ? { sourceHash: n.sourceHash } : {}),
|
|
251
|
+
...(n.stale ? { stale: true } : {}),
|
|
252
|
+
...(badges ? { badges } : {}),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
export function finalEdge(e) {
|
|
256
|
+
return {
|
|
257
|
+
from: e.from, to: e.to, kind: e.kind, weight: round6(e.weight), origin: e.origin,
|
|
258
|
+
...(e.confidence !== undefined ? { confidence: round6(e.confidence) } : {}),
|
|
259
|
+
...(e.verdict ? { verdict: e.verdict } : {}),
|
|
260
|
+
...(e.cycle ? { cycle: true } : {}),
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/knowledge/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* knowledge/cards.ts — `toCards`: one knowledge-index card per graph node
|
|
3
|
+
* (design: Builderforce.ai/docs/design/deterministic-knowledge-index.md, "Cards").
|
|
4
|
+
*
|
|
5
|
+
* | kind | text | keys |
|
|
6
|
+
* |-----------------|-------------------------------------------------------------------|-------------------------------|
|
|
7
|
+
* | file | path · area · partition · symbols · doc line · top-5 neighbours | path, basename, symbols, area |
|
|
8
|
+
* | section | file · breadcrumb · first 400 chars · outgoing link targets | file path, slug, front matter |
|
|
9
|
+
* | entity (ent:) | name · type · top-5 mentioning sources | normalized name, aliases |
|
|
10
|
+
* | claim | subject predicate object · quote · source section | subject/object entity keys |
|
|
11
|
+
* | area | path · partition · top-10 members | path |
|
|
12
|
+
*
|
|
13
|
+
* `hash` is the index's own text hash (`hashDocText`), so an unchanged card is never re-embedded.
|
|
14
|
+
*/
|
|
15
|
+
import type { IndexDoc, KnowledgeGraph } from './model.js';
|
|
16
|
+
export declare function toCards(g: KnowledgeGraph): IndexDoc[];
|
|
17
|
+
//# sourceMappingURL=cards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cards.d.ts","sourceRoot":"","sources":["../../src/knowledge/cards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAgB,cAAc,EAAW,MAAM,YAAY,CAAC;AAQlF,wBAAgB,OAAO,CAAC,CAAC,EAAE,cAAc,GAAG,QAAQ,EAAE,CAkBrD"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* knowledge/cards.ts — `toCards`: one knowledge-index card per graph node
|
|
3
|
+
* (design: Builderforce.ai/docs/design/deterministic-knowledge-index.md, "Cards").
|
|
4
|
+
*
|
|
5
|
+
* | kind | text | keys |
|
|
6
|
+
* |-----------------|-------------------------------------------------------------------|-------------------------------|
|
|
7
|
+
* | file | path · area · partition · symbols · doc line · top-5 neighbours | path, basename, symbols, area |
|
|
8
|
+
* | section | file · breadcrumb · first 400 chars · outgoing link targets | file path, slug, front matter |
|
|
9
|
+
* | entity (ent:) | name · type · top-5 mentioning sources | normalized name, aliases |
|
|
10
|
+
* | claim | subject predicate object · quote · source section | subject/object entity keys |
|
|
11
|
+
* | area | path · partition · top-10 members | path |
|
|
12
|
+
*
|
|
13
|
+
* `hash` is the index's own text hash (`hashDocText`), so an unchanged card is never re-embedded.
|
|
14
|
+
*/
|
|
15
|
+
import { hashDocText } from '../retrieval/knowledge-index/digest.js';
|
|
16
|
+
import { byImportance } from './importance.js';
|
|
17
|
+
import { entityName } from './resolve.js';
|
|
18
|
+
import { basenameOf, compareStr, fileRefOf, normalizeKey, pathOfRef, slugOf } from './refs.js';
|
|
19
|
+
const SEP = ' · ';
|
|
20
|
+
const EXCERPT_CHARS = 400;
|
|
21
|
+
export function toCards(g) {
|
|
22
|
+
const byRef = new Map(g.nodes.map((n) => [n.ref, n]));
|
|
23
|
+
const outEdges = new Map();
|
|
24
|
+
const inEdges = new Map();
|
|
25
|
+
const push = (m, k, e) => {
|
|
26
|
+
const l = m.get(k) ?? [];
|
|
27
|
+
l.push(e);
|
|
28
|
+
m.set(k, l);
|
|
29
|
+
};
|
|
30
|
+
for (const e of g.edges) {
|
|
31
|
+
push(outEdges, e.from, e);
|
|
32
|
+
push(inEdges, e.to, e);
|
|
33
|
+
}
|
|
34
|
+
const label = (r) => byRef.get(r)?.label ?? pathOfRef(r) ?? r;
|
|
35
|
+
const ctx = { byRef, outEdges, inEdges, label, members: membersByArea(g.nodes) };
|
|
36
|
+
return g.nodes.map((n) => {
|
|
37
|
+
const { text, keys } = cardOf(n, ctx);
|
|
38
|
+
const uniqueKeys = [...new Set(keys.filter(Boolean))].sort(compareStr);
|
|
39
|
+
return { id: n.ref, text, ...(uniqueKeys.length ? { keys: uniqueKeys } : {}), hash: hashDocText(text) };
|
|
40
|
+
}).sort((a, b) => compareStr(a.id, b.id));
|
|
41
|
+
}
|
|
42
|
+
function membersByArea(nodes) {
|
|
43
|
+
const out = new Map();
|
|
44
|
+
for (const n of nodes) {
|
|
45
|
+
if (!n.area || n.kind !== 'file')
|
|
46
|
+
continue;
|
|
47
|
+
const l = out.get(n.area) ?? [];
|
|
48
|
+
l.push(n);
|
|
49
|
+
out.set(n.area, l);
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
/** Neighbour refs (either direction), heaviest first, then by ref. */
|
|
54
|
+
function topNeighbours(ref, ctx, n) {
|
|
55
|
+
const scored = new Map();
|
|
56
|
+
for (const e of ctx.outEdges.get(ref) ?? [])
|
|
57
|
+
scored.set(e.to, Math.max(scored.get(e.to) ?? 0, e.weight));
|
|
58
|
+
for (const e of ctx.inEdges.get(ref) ?? [])
|
|
59
|
+
scored.set(e.from, Math.max(scored.get(e.from) ?? 0, e.weight));
|
|
60
|
+
return [...scored].sort((a, b) => b[1] - a[1] || compareStr(a[0], b[0])).slice(0, n).map(([r]) => r);
|
|
61
|
+
}
|
|
62
|
+
const badge = (n, k) => {
|
|
63
|
+
const v = n?.badges?.[k];
|
|
64
|
+
return v === undefined || v === '' ? undefined : String(v);
|
|
65
|
+
};
|
|
66
|
+
const frontMatter = (n) => Object.keys(n?.badges ?? {}).filter((k) => k.startsWith('fm.')).sort(compareStr)
|
|
67
|
+
.flatMap((k) => String(n.badges[k]).split(',').map((v) => normalizeKey(v)));
|
|
68
|
+
function cardOf(n, ctx) {
|
|
69
|
+
const path = pathOfRef(n.ref) ?? '';
|
|
70
|
+
const join = (parts) => parts.filter((p) => p !== undefined && p !== '').join(SEP);
|
|
71
|
+
switch (n.kind) {
|
|
72
|
+
case 'file': {
|
|
73
|
+
const contained = (ctx.outEdges.get(n.ref) ?? []).filter((e) => e.kind === 'contains')
|
|
74
|
+
.map((e) => ctx.byRef.get(e.to)).filter((c) => c?.kind === 'symbol');
|
|
75
|
+
const symbols = contained.map((s) => s.label).sort(compareStr);
|
|
76
|
+
return {
|
|
77
|
+
text: join([path, n.area && pathOfRef(n.area), n.partition, symbols.join(', '), badge(n, 'doc'),
|
|
78
|
+
topNeighbours(n.ref, ctx, 5).map(ctx.label).join(', ')]),
|
|
79
|
+
keys: [path, basenameOf(path), ...symbols, n.area ? pathOfRef(n.area) ?? '' : ''],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
case 'section': {
|
|
83
|
+
const file = ctx.byRef.get(fileRefOf(n.ref));
|
|
84
|
+
const links = (ctx.outEdges.get(n.ref) ?? []).filter((e) => e.kind === 'links')
|
|
85
|
+
.map((e) => pathOfRef(e.to) ?? e.to).sort(compareStr);
|
|
86
|
+
return {
|
|
87
|
+
text: join([path, badge(n, 'breadcrumb') ?? n.label, badge(n, 'excerpt')?.slice(0, EXCERPT_CHARS), links.join(', ')]),
|
|
88
|
+
keys: [path, slugOf(n.label), ...frontMatter(file)],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
case 'entity': {
|
|
92
|
+
const sources = (ctx.inEdges.get(n.ref) ?? []).filter((e) => e.kind === 'mentions' || e.kind === 'about')
|
|
93
|
+
.map((e) => ctx.byRef.get(e.from)).filter((s) => !!s);
|
|
94
|
+
const about = (ctx.outEdges.get(n.ref) ?? []).filter((e) => e.kind === 'about')
|
|
95
|
+
.map((e) => ctx.byRef.get(e.to)).filter((s) => !!s);
|
|
96
|
+
const top = [...new Map([...sources, ...about].map((s) => [s.ref, s])).values()].sort(byImportance).slice(0, 5);
|
|
97
|
+
const name = entityName(n.ref);
|
|
98
|
+
return {
|
|
99
|
+
text: join([n.label, badge(n, 'type'), top.map((s) => s.label).join(', ')]),
|
|
100
|
+
keys: [normalizeKey(name), normalizeKey(n.label.replace(/\s*\([^)]*\)\s*$/, '')),
|
|
101
|
+
...String(badge(n, 'aliases') ?? '').split(',').map(normalizeKey)],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
case 'claim': {
|
|
105
|
+
const out = ctx.outEdges.get(n.ref) ?? [];
|
|
106
|
+
const sections = out.filter((e) => e.kind === 'about').map((e) => ctx.label(e.to)).sort(compareStr);
|
|
107
|
+
const entities = out.filter((e) => e.kind === 'mentions' && e.to.startsWith('ent:')).map((e) => normalizeKey(entityName(e.to)));
|
|
108
|
+
return { text: join([n.label, sections.join(', ')]), keys: entities };
|
|
109
|
+
}
|
|
110
|
+
case 'area': {
|
|
111
|
+
const members = [...(ctx.members.get(n.ref) ?? [])].sort(byImportance).slice(0, 10).map((m) => m.label);
|
|
112
|
+
return { text: join([path, n.partition, members.join(', ')]), keys: [path] };
|
|
113
|
+
}
|
|
114
|
+
default:
|
|
115
|
+
return { text: join([n.label, n.kind, path]), keys: [normalizeKey(n.label), path] };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=cards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cards.js","sourceRoot":"","sources":["../../src/knowledge/cards.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* knowledge/findings.ts — what a person can act on (PRD 38 §3.5).
|
|
3
|
+
*
|
|
4
|
+
* Generic findings, for every pack: cycle, clone group, near-duplicate, partition
|
|
5
|
+
* violation, unpartitioned share, stale knowledge — plus `possible-same` entities. Packs
|
|
6
|
+
* add their own through {@link FindingRule}s. Every finding has a stable id (a hash of its
|
|
7
|
+
* kind and refs) and a `requestKey` under `knowledgeGraph.fix.*`: the fixed, prefilled
|
|
8
|
+
* Fix-with-agent request, never a model call.
|
|
9
|
+
*/
|
|
10
|
+
import type { Finding, KEdge, KnowledgeGraph, KnowledgePack, NodeRef, PartitionRegistry } from './model.js';
|
|
11
|
+
import type { SimilarPair } from '../retrieval/knowledge-index/types.js';
|
|
12
|
+
/** Node badge naming the clone group (e.g. a jscpd issue id) its `duplicate` edges belong to. */
|
|
13
|
+
export declare const CLONE_GROUP_BADGE = "cloneGroup";
|
|
14
|
+
/** Refs listed on one grouped finding, at most (the count rides in params). */
|
|
15
|
+
export declare const MAX_FINDING_NODES = 50;
|
|
16
|
+
export declare function findingId(kind: string, refs: readonly string[]): string;
|
|
17
|
+
/** `clone-group` → `knowledgeGraph.fix.cloneGroup`. */
|
|
18
|
+
export declare function requestKeyFor(kind: string): string;
|
|
19
|
+
/** Connected components over edges, each sorted; components sorted by first ref. */
|
|
20
|
+
export declare function components(edges: readonly KEdge[]): NodeRef[][];
|
|
21
|
+
export declare function genericFindings(g: KnowledgeGraph, registries: ReadonlyMap<string, PartitionRegistry>): Finding[];
|
|
22
|
+
/** Generic + possible-same + every pack's rules; deduped by id; severity, then id. */
|
|
23
|
+
export declare function computeFindings(g: KnowledgeGraph, packs: readonly KnowledgePack[], registries: ReadonlyMap<string, PartitionRegistry>, nearDuplicates: readonly SimilarPair[]): Finding[];
|
|
24
|
+
//# sourceMappingURL=findings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findings.d.ts","sourceRoot":"","sources":["../../src/knowledge/findings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAS,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACnH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAIzE,iGAAiG;AACjG,eAAO,MAAM,iBAAiB,eAAe,CAAC;AAC9C,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAIpC,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEvE;AAED,uDAAuD;AACvD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAUD,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,KAAK,EAAE,GAAG,OAAO,EAAE,EAAE,CAqB/D;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,OAAO,EAAE,CAqDhH;AAkBD,sFAAsF;AACtF,wBAAgB,eAAe,CAC3B,CAAC,EAAE,cAAc,EACjB,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAClD,cAAc,EAAE,SAAS,WAAW,EAAE,GACvC,OAAO,EAAE,CAiBX"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* knowledge/findings.ts — what a person can act on (PRD 38 §3.5).
|
|
3
|
+
*
|
|
4
|
+
* Generic findings, for every pack: cycle, clone group, near-duplicate, partition
|
|
5
|
+
* violation, unpartitioned share, stale knowledge — plus `possible-same` entities. Packs
|
|
6
|
+
* add their own through {@link FindingRule}s. Every finding has a stable id (a hash of its
|
|
7
|
+
* kind and refs) and a `requestKey` under `knowledgeGraph.fix.*`: the fixed, prefilled
|
|
8
|
+
* Fix-with-agent request, never a model call.
|
|
9
|
+
*/
|
|
10
|
+
import { hashText } from '../ingest/hash.js';
|
|
11
|
+
import { possibleSameFindings } from './resolve.js';
|
|
12
|
+
import { compareStr, round6 } from './refs.js';
|
|
13
|
+
/** Node badge naming the clone group (e.g. a jscpd issue id) its `duplicate` edges belong to. */
|
|
14
|
+
export const CLONE_GROUP_BADGE = 'cloneGroup';
|
|
15
|
+
/** Refs listed on one grouped finding, at most (the count rides in params). */
|
|
16
|
+
export const MAX_FINDING_NODES = 50;
|
|
17
|
+
const SEVERITY_RANK = { error: 0, warn: 1, info: 2 };
|
|
18
|
+
export function findingId(kind, refs) {
|
|
19
|
+
return `${kind}:${hashText([...refs].sort(compareStr).join('\u0000'))}`;
|
|
20
|
+
}
|
|
21
|
+
/** `clone-group` → `knowledgeGraph.fix.cloneGroup`. */
|
|
22
|
+
export function requestKeyFor(kind) {
|
|
23
|
+
return `knowledgeGraph.fix.${kind.replace(/-([a-z])/g, (_, c) => c.toUpperCase())}`;
|
|
24
|
+
}
|
|
25
|
+
function finding(kind, pack, nodes, severity, params) {
|
|
26
|
+
const sorted = [...new Set(nodes)].sort(compareStr);
|
|
27
|
+
return {
|
|
28
|
+
id: findingId(kind, sorted), kind, pack, nodes: sorted.slice(0, MAX_FINDING_NODES), severity, params,
|
|
29
|
+
requestKey: requestKeyFor(kind),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Connected components over edges, each sorted; components sorted by first ref. */
|
|
33
|
+
export function components(edges) {
|
|
34
|
+
const parent = new Map();
|
|
35
|
+
const find = (x) => {
|
|
36
|
+
let r = x;
|
|
37
|
+
while (parent.get(r) !== r)
|
|
38
|
+
r = parent.get(r);
|
|
39
|
+
parent.set(x, r);
|
|
40
|
+
return r;
|
|
41
|
+
};
|
|
42
|
+
for (const e of edges) {
|
|
43
|
+
for (const r of [e.from, e.to])
|
|
44
|
+
if (!parent.has(r))
|
|
45
|
+
parent.set(r, r);
|
|
46
|
+
const a = find(e.from), b = find(e.to);
|
|
47
|
+
if (a !== b)
|
|
48
|
+
parent.set(compareStr(a, b) < 0 ? b : a, compareStr(a, b) < 0 ? a : b);
|
|
49
|
+
}
|
|
50
|
+
const groups = new Map();
|
|
51
|
+
for (const r of [...parent.keys()].sort(compareStr)) {
|
|
52
|
+
const root = find(r);
|
|
53
|
+
let g = groups.get(root);
|
|
54
|
+
if (!g)
|
|
55
|
+
groups.set(root, (g = []));
|
|
56
|
+
g.push(r);
|
|
57
|
+
}
|
|
58
|
+
return [...groups.values()].sort((a, b) => compareStr(a[0], b[0]));
|
|
59
|
+
}
|
|
60
|
+
export function genericFindings(g, registries) {
|
|
61
|
+
const byRef = new Map(g.nodes.map((n) => [n.ref, n]));
|
|
62
|
+
const packOf = (ref) => byRef.get(ref)?.pack ?? 'memory';
|
|
63
|
+
const out = [];
|
|
64
|
+
for (const refs of components(g.edges.filter((e) => e.cycle))) {
|
|
65
|
+
out.push(finding('cycle', packOf(refs[0]), refs, 'warn', { nodes: refs.length }));
|
|
66
|
+
}
|
|
67
|
+
// Clone groups: duplicate edges grouped by the clone-group badge, else by component.
|
|
68
|
+
const dup = g.edges.filter((e) => e.kind === 'duplicate');
|
|
69
|
+
const byBadge = new Map();
|
|
70
|
+
const unbadged = [];
|
|
71
|
+
for (const e of dup) {
|
|
72
|
+
const badge = byRef.get(e.from)?.badges?.[CLONE_GROUP_BADGE] ?? byRef.get(e.to)?.badges?.[CLONE_GROUP_BADGE];
|
|
73
|
+
if (badge === undefined) {
|
|
74
|
+
unbadged.push(e);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const list = byBadge.get(String(badge)) ?? [];
|
|
78
|
+
list.push(e);
|
|
79
|
+
byBadge.set(String(badge), list);
|
|
80
|
+
}
|
|
81
|
+
const groups = [
|
|
82
|
+
...[...byBadge].map(([group, es]) => ({ group, refs: es.flatMap((e) => [e.from, e.to]) })),
|
|
83
|
+
...components(unbadged).map((refs) => ({ group: '', refs })),
|
|
84
|
+
];
|
|
85
|
+
for (const { group, refs } of groups) {
|
|
86
|
+
const unique = [...new Set(refs)];
|
|
87
|
+
out.push(finding('clone-group', packOf(unique.sort(compareStr)[0]), unique, 'warn', { group, members: unique.length }));
|
|
88
|
+
}
|
|
89
|
+
for (const e of g.edges) {
|
|
90
|
+
if (e.kind === 'near-duplicate') {
|
|
91
|
+
out.push(finding('near-duplicate', packOf(e.from), [e.from, e.to], 'info', { similarity: round6(e.weight) }));
|
|
92
|
+
}
|
|
93
|
+
if (e.verdict === 'upward' || e.verdict === 'skips') {
|
|
94
|
+
const from = byRef.get(e.from), to = byRef.get(e.to);
|
|
95
|
+
out.push(finding('partition-violation', packOf(e.from), [e.from, e.to], e.verdict === 'upward' ? 'error' : 'warn', {
|
|
96
|
+
verdict: e.verdict, from: from?.partition ?? '', to: to?.partition ?? '', kind: e.kind,
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
for (const [pack, reg] of [...registries].sort((a, b) => compareStr(a[0], b[0]))) {
|
|
101
|
+
if (!reg.allow)
|
|
102
|
+
continue;
|
|
103
|
+
const files = g.nodes.filter((n) => n.pack === pack && n.kind === 'file');
|
|
104
|
+
const loose = files.filter((n) => n.partition === undefined).map((n) => n.ref);
|
|
105
|
+
if (loose.length === 0)
|
|
106
|
+
continue;
|
|
107
|
+
out.push(finding('unpartitioned', pack, loose, 'info', {
|
|
108
|
+
count: loose.length, total: files.length, share: Math.round((loose.length / files.length) * 100),
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
out.push(...staleFindings(g, byRef));
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
/** One finding per source whose stored knowledge went stale (unanchored stale nodes: one each). */
|
|
115
|
+
function staleFindings(g, byRef) {
|
|
116
|
+
const about = new Map();
|
|
117
|
+
for (const e of g.edges)
|
|
118
|
+
if (e.kind === 'about' && !about.has(e.from))
|
|
119
|
+
about.set(e.from, e.to);
|
|
120
|
+
const bySource = new Map();
|
|
121
|
+
for (const n of g.nodes) {
|
|
122
|
+
if (!n.stale)
|
|
123
|
+
continue;
|
|
124
|
+
const target = about.get(n.ref) ?? n.ref;
|
|
125
|
+
const list = bySource.get(target) ?? [];
|
|
126
|
+
list.push(n.ref);
|
|
127
|
+
bySource.set(target, list);
|
|
128
|
+
}
|
|
129
|
+
return [...bySource].map(([source, refs]) => finding('stale', byRef.get(source)?.pack ?? 'memory', [source, ...refs], 'warn', { count: refs.length }));
|
|
130
|
+
}
|
|
131
|
+
/** Generic + possible-same + every pack's rules; deduped by id; severity, then id. */
|
|
132
|
+
export function computeFindings(g, packs, registries, nearDuplicates) {
|
|
133
|
+
const all = [...genericFindings(g, registries), ...possibleSameFindings(nearDuplicates)];
|
|
134
|
+
for (const pack of [...packs].sort((a, b) => compareStr(a.id, b.id))) {
|
|
135
|
+
for (const rule of pack.findings ?? []) {
|
|
136
|
+
for (const f of rule.find(g)) {
|
|
137
|
+
all.push({
|
|
138
|
+
...f,
|
|
139
|
+
id: f.id || findingId(f.kind, f.nodes),
|
|
140
|
+
nodes: [...new Set(f.nodes)].sort(compareStr),
|
|
141
|
+
requestKey: f.requestKey ?? requestKeyFor(f.kind),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const byId = new Map();
|
|
147
|
+
for (const f of all)
|
|
148
|
+
if (!byId.has(f.id))
|
|
149
|
+
byId.set(f.id, f);
|
|
150
|
+
return [...byId.values()].sort((a, b) => SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity] || compareStr(a.id, b.id));
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=findings.js.map
|