@unerr-ai/unerr 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -194
- package/dist/cli.js +39149 -36991
- package/package.json +9 -2
- package/dist/__tests__/architecture-guard.test.js +0 -122
- package/dist/__tests__/arg-validator.test.js +0 -205
- package/dist/__tests__/ast-extractor.test.js +0 -203
- package/dist/__tests__/auto-bootstrap.test.js +0 -280
- package/dist/__tests__/background-indexer.test.js +0 -228
- package/dist/__tests__/blast-radius-engine.test.js +0 -200
- package/dist/__tests__/bridge-isolation.test.js +0 -37
- package/dist/__tests__/budget-enforcer.test.js +0 -53
- package/dist/__tests__/cfg-test-detection-perf.test.js +0 -82
- package/dist/__tests__/change-narrative.test.js +0 -190
- package/dist/__tests__/check-commit.test.js +0 -258
- package/dist/__tests__/checksum.test.js +0 -34
- package/dist/__tests__/commit-watcher.test.js +0 -154
- package/dist/__tests__/community-detection.test.js +0 -179
- package/dist/__tests__/community-tools.test.js +0 -299
- package/dist/__tests__/components.test.js +0 -449
- package/dist/__tests__/compression-log.test.js +0 -174
- package/dist/__tests__/compression-quality-monitor.test.js +0 -40
- package/dist/__tests__/config-healer.test.js +0 -165
- package/dist/__tests__/context-ledger.test.js +0 -58
- package/dist/__tests__/convention-detector.test.js +0 -99
- package/dist/__tests__/convention-learner.test.js +0 -86
- package/dist/__tests__/correction-detector.test.js +0 -330
- package/dist/__tests__/daemon-autostart-install.test.js +0 -283
- package/dist/__tests__/daemon-bridge.test.js +0 -222
- package/dist/__tests__/daemon-dashboard.test.js +0 -202
- package/dist/__tests__/daemon-registry.test.js +0 -240
- package/dist/__tests__/daemon-supervisor.test.js +0 -318
- package/dist/__tests__/daemon-version-check.test.js +0 -275
- package/dist/__tests__/decision-point-detector.test.js +0 -98
- package/dist/__tests__/deep-link.test.js +0 -143
- package/dist/__tests__/disallowed-tools.test.js +0 -115
- package/dist/__tests__/drift-tracker.test.js +0 -582
- package/dist/__tests__/durability-scorer.test.js +0 -152
- package/dist/__tests__/efficiency-tracker.test.js +0 -65
- package/dist/__tests__/enrich.test.js +0 -144
- package/dist/__tests__/entity-rewind.test.js +0 -248
- package/dist/__tests__/ephemeral.test.js +0 -111
- package/dist/__tests__/exploration-cost.test.js +0 -93
- package/dist/__tests__/fact-generator.test.js +0 -197
- package/dist/__tests__/file-l0-graph.test.js +0 -244
- package/dist/__tests__/file-logger.test.js +0 -82
- package/dist/__tests__/file-outline.test.js +0 -141
- package/dist/__tests__/file-read-protocol.test.js +0 -188
- package/dist/__tests__/format-encoder.test.js +0 -233
- package/dist/__tests__/git-attribution.test.js +0 -259
- package/dist/__tests__/graph-temporal-joiner.test.js +0 -219
- package/dist/__tests__/health-grade-enhanced.test.js +0 -138
- package/dist/__tests__/health-map-data.test.js +0 -173
- package/dist/__tests__/helpers/mcp-harness.js +0 -45
- package/dist/__tests__/helpers/mcp-harness.test.js +0 -68
- package/dist/__tests__/hook-dedup.test.js +0 -112
- package/dist/__tests__/hook-runner.test.js +0 -253
- package/dist/__tests__/indexer-cfg.test.js +0 -185
- package/dist/__tests__/indexer-cross-file.test.js +0 -172
- package/dist/__tests__/indexer-extraction.test.js +0 -245
- package/dist/__tests__/indexer-incremental.test.js +0 -232
- package/dist/__tests__/indexer-language-expansion.test.js +0 -165
- package/dist/__tests__/init-push.test.js +0 -131
- package/dist/__tests__/instruction-writer.test.js +0 -179
- package/dist/__tests__/intelligence-integration.test.js +0 -217
- package/dist/__tests__/intent-correlator.test.js +0 -175
- package/dist/__tests__/intent-detector.test.js +0 -235
- package/dist/__tests__/intent-encoder.test.js +0 -167
- package/dist/__tests__/java-build-tool-detection.test.js +0 -174
- package/dist/__tests__/layer3-sprint-q.test.js +0 -160
- package/dist/__tests__/layer3-sprint-r.test.js +0 -91
- package/dist/__tests__/layer3-sprint-s.test.js +0 -183
- package/dist/__tests__/layer3-sprint-t.test.js +0 -201
- package/dist/__tests__/layer3-sprint-u.test.js +0 -174
- package/dist/__tests__/layer4-sprint-ba2.test.js +0 -354
- package/dist/__tests__/layer4-sprint-ba4.test.js +0 -84
- package/dist/__tests__/layer4-sprint-vs.test.js +0 -105
- package/dist/__tests__/ledger-chains.test.js +0 -162
- package/dist/__tests__/lifecycle-machine.test.js +0 -226
- package/dist/__tests__/local-chat-provider.test.js +0 -170
- package/dist/__tests__/local-convention-detector.test.js +0 -308
- package/dist/__tests__/local-embeddings.test.js +0 -422
- package/dist/__tests__/local-graph.test.js +0 -540
- package/dist/__tests__/local-indexer.test.js +0 -228
- package/dist/__tests__/local-intelligence-l3.test.js +0 -332
- package/dist/__tests__/local-llm.test.js +0 -253
- package/dist/__tests__/local-mode-offline.test.js +0 -187
- package/dist/__tests__/local-mode-stats.test.js +0 -273
- package/dist/__tests__/local-mode-tui.test.js +0 -343
- package/dist/__tests__/local-parse.test.js +0 -199
- package/dist/__tests__/log-tailer.test.js +0 -208
- package/dist/__tests__/loop-breaker.test.js +0 -276
- package/dist/__tests__/loop-miner.test.js +0 -226
- package/dist/__tests__/mcp-config.test.js +0 -126
- package/dist/__tests__/mcp-content-json.test.js +0 -10
- package/dist/__tests__/mcp-envelope.test.js +0 -124
- package/dist/__tests__/metrics-store.test.js +0 -223
- package/dist/__tests__/native-watcher.test.js +0 -191
- package/dist/__tests__/navigation-hooks-agent-aware.test.js +0 -145
- package/dist/__tests__/negative-knowledge.test.js +0 -116
- package/dist/__tests__/network-boundary.test.js +0 -190
- package/dist/__tests__/network-firewall.test.js +0 -112
- package/dist/__tests__/nudge-invariants.test.js +0 -160
- package/dist/__tests__/nudge-v2.test.js +0 -225
- package/dist/__tests__/offline-rewind.test.js +0 -251
- package/dist/__tests__/open-threads.test.js +0 -89
- package/dist/__tests__/output-compressor.test.js +0 -93
- package/dist/__tests__/pending-violations.test.js +0 -112
- package/dist/__tests__/persistence-effectiveness.test.js +0 -143
- package/dist/__tests__/provider-factory.test.js +0 -42
- package/dist/__tests__/providers.test.js +0 -24
- package/dist/__tests__/proxy.test.js +0 -314
- package/dist/__tests__/query-router.test.js +0 -1018
- package/dist/__tests__/reasoning-quality-route.test.js +0 -138
- package/dist/__tests__/redactor.test.js +0 -120
- package/dist/__tests__/resource-monitor.test.js +0 -57
- package/dist/__tests__/response-envelope.test.js +0 -100
- package/dist/__tests__/risk-classifier.test.js +0 -101
- package/dist/__tests__/risk-signal-scope.test.js +0 -75
- package/dist/__tests__/rule-evaluator.test.js +0 -280
- package/dist/__tests__/scip-decoder.test.js +0 -49
- package/dist/__tests__/scip-downloader.test.js +0 -201
- package/dist/__tests__/scip-merger.test.js +0 -103
- package/dist/__tests__/search-index.test.js +0 -422
- package/dist/__tests__/semantic-enrichment.test.js +0 -360
- package/dist/__tests__/session-brief-builder.test.js +0 -187
- package/dist/__tests__/session-context.test.js +0 -221
- package/dist/__tests__/session-continuity.test.js +0 -144
- package/dist/__tests__/session-dedup.test.js +0 -74
- package/dist/__tests__/session-event-wiring.test.js +0 -206
- package/dist/__tests__/session-events.test.js +0 -149
- package/dist/__tests__/session-legend.test.js +0 -20
- package/dist/__tests__/session-persistence.test.js +0 -131
- package/dist/__tests__/session-resume-block.test.js +0 -107
- package/dist/__tests__/session-resume.test.js +0 -97
- package/dist/__tests__/session-summary-writer.test.js +0 -134
- package/dist/__tests__/shadow-ledger.test.js +0 -203
- package/dist/__tests__/shell-classifier.test.js +0 -151
- package/dist/__tests__/shell-compression-floor.test.js +0 -189
- package/dist/__tests__/shell-compression-v2.test.js +0 -339
- package/dist/__tests__/shell-compressor.test.js +0 -35
- package/dist/__tests__/shell-hooks.test.js +0 -128
- package/dist/__tests__/shell-strategies.test.js +0 -644
- package/dist/__tests__/shell-tee.test.js +0 -133
- package/dist/__tests__/signal-dedup.test.js +0 -158
- package/dist/__tests__/signal-reinforcer.test.js +0 -77
- package/dist/__tests__/signal-scorer.test.js +0 -251
- package/dist/__tests__/signal-show-store.test.js +0 -108
- package/dist/__tests__/smart-truncate.test.js +0 -215
- package/dist/__tests__/snapshot-v2.test.js +0 -113
- package/dist/__tests__/sprint-l1-local-mode.test.js +0 -130
- package/dist/__tests__/sprint-l10-boot.test.js +0 -220
- package/dist/__tests__/sprint-l9-offline-commands.test.js +0 -189
- package/dist/__tests__/sprint-q-persistent-context.test.js +0 -198
- package/dist/__tests__/sprint-s1-wiring.test.js +0 -215
- package/dist/__tests__/sprint-s2-wiring.test.js +0 -256
- package/dist/__tests__/sprint-s3-wiring.test.js +0 -195
- package/dist/__tests__/sprint-s4-wiring.test.js +0 -213
- package/dist/__tests__/sprint-s6-hooks.test.js +0 -222
- package/dist/__tests__/sprint-s7-persistent.test.js +0 -263
- package/dist/__tests__/sprint-s8-value.test.js +0 -167
- package/dist/__tests__/sprint-s9-behavioral.test.js +0 -179
- package/dist/__tests__/sprint3-intelligence.test.js +0 -297
- package/dist/__tests__/sprint5-mcp-server.test.js +0 -136
- package/dist/__tests__/startup-display.test.js +0 -302
- package/dist/__tests__/startup-log-file.test.js +0 -97
- package/dist/__tests__/stash-manager.test.js +0 -229
- package/dist/__tests__/state-detector.test.js +0 -92
- package/dist/__tests__/status-dashboard.test.js +0 -142
- package/dist/__tests__/temporal-facts.test.js +0 -292
- package/dist/__tests__/temporal-routes.test.js +0 -142
- package/dist/__tests__/test-detector.test.js +0 -174
- package/dist/__tests__/theme.test.js +0 -72
- package/dist/__tests__/timeline-agents.test.js +0 -122
- package/dist/__tests__/timeline-bootstrap.test.js +0 -176
- package/dist/__tests__/timeline-filters.test.js +0 -193
- package/dist/__tests__/timeline-markers.test.js +0 -151
- package/dist/__tests__/timeline-routes.test.js +0 -156
- package/dist/__tests__/timeline-store.test.js +0 -171
- package/dist/__tests__/token-counter.test.js +0 -86
- package/dist/__tests__/token-estimator.test.js +0 -96
- package/dist/__tests__/token-flow-api.test.js +0 -239
- package/dist/__tests__/token-flow-instrumentation.test.js +0 -437
- package/dist/__tests__/token-flow-persistence.test.js +0 -356
- package/dist/__tests__/token-flow-routes.test.js +0 -199
- package/dist/__tests__/token-flow.test.js +0 -695
- package/dist/__tests__/tool-clusters.test.js +0 -177
- package/dist/__tests__/transport-mux.test.js +0 -283
- package/dist/__tests__/turn-segmenter.test.js +0 -166
- package/dist/__tests__/uninstall.test.js +0 -141
- package/dist/__tests__/warm-start-policy.test.js +0 -271
- package/dist/__tests__/wire-cap-nudge.test.js +0 -77
- package/dist/__tests__/worker-pool.test.js +0 -101
- package/dist/ui/assets/index-7gl3mIuY.css +0 -1
- package/dist/ui/assets/index-CX4FCWGT.js +0 -10
- package/dist/ui/assets/rolldown-runtime-S-ySWqyJ.js +0 -1
- package/dist/ui/assets/vis-network-NIJHUFI3.js +0 -908
- package/dist/ui/fonts/jetbrains-mono-latin-400-normal.woff +0 -0
- package/dist/ui/icon-wordmark.png +0 -0
- package/dist/ui/icon-wordmark.svg +0 -30
- package/dist/ui/icon.png +0 -0
- package/dist/ui/icon.svg +0 -25
- package/dist/ui/index.html +0 -15
- package/dist/ui/prototype-sandbox/index.html +0 -257
- package/dist/ui/screenshots/activity.png +0 -0
- package/dist/ui/screenshots/code-base-intelligence.png +0 -0
- package/dist/ui/screenshots/dashboard.png +0 -0
- package/dist/ui/screenshots/project-memory.png +0 -0
- package/dist/ui/screenshots/reasoning-quality.png +0 -0
- package/dist/ui/screenshots/reasoning-session.png +0 -0
- package/dist/ui/screenshots/token-session.png +0 -0
- package/dist/ui/screenshots/token-trace-main.png +0 -0
- package/dist/ui/screenshots/token-turn.png +0 -0
- package/dist/ui/unerr-wordmark.png +0 -0
- package/dist/ui/unerr-wordmark.svg +0 -9
- package/dist/ui/unerr.png +0 -0
- package/dist/ui/unerr.svg +0 -25
- package/dist/ui/web-app-manifest-192x192.png +0 -0
- package/dist/ui/web-app-manifest-512x512.png +0 -0
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sprint SE.11-SE.15: Semantic enrichment tests.
|
|
3
|
-
*
|
|
4
|
-
* Tests: identifier tokenizer, TF-IDF, Node2Vec, similarity engine.
|
|
5
|
-
*/
|
|
6
|
-
import { describe, expect, it } from "vitest";
|
|
7
|
-
import { extractDocComment, extractDocTags, } from "../intelligence/semantic/docstring-extractor.js";
|
|
8
|
-
import { cosineSimilarity, decodeEmbedding, encodeEmbedding, findSimilar, } from "../intelligence/semantic/embedding-store.js";
|
|
9
|
-
import { runEnrichment } from "../intelligence/semantic/enrichment-orchestrator.js";
|
|
10
|
-
import { extractKeywords } from "../intelligence/semantic/git-message-miner.js";
|
|
11
|
-
import { buildTokenFrequency, tokenizeFilePath, tokenizeIdentifier, } from "../intelligence/semantic/identifier-tokenizer.js";
|
|
12
|
-
import { STRUCTURAL_DIM, combineEmbeddings, trainEmbeddings, } from "../intelligence/semantic/node2vec-embeddings.js";
|
|
13
|
-
import { buildAdjacencyFromEdges, generateWalks, } from "../intelligence/semantic/node2vec-walks.js";
|
|
14
|
-
import { getPrimaryDomain, inferDomain, } from "../intelligence/semantic/path-domain-inference.js";
|
|
15
|
-
import { computeSimilarity, findMostSimilar, } from "../intelligence/semantic/similarity-engine.js";
|
|
16
|
-
import { VECTOR_DIM, buildCorpus, buildTfIdfVectors, computeTfIdfVector, } from "../intelligence/semantic/tfidf-vectors.js";
|
|
17
|
-
describe("Identifier Tokenizer (SE.1)", () => {
|
|
18
|
-
it("tokenizes camelCase", () => {
|
|
19
|
-
expect(tokenizeIdentifier("getUserProfile")).toEqual([
|
|
20
|
-
"get",
|
|
21
|
-
"user",
|
|
22
|
-
"profile",
|
|
23
|
-
]);
|
|
24
|
-
});
|
|
25
|
-
it("tokenizes PascalCase", () => {
|
|
26
|
-
expect(tokenizeIdentifier("UserService")).toEqual(["user", "service"]);
|
|
27
|
-
});
|
|
28
|
-
it("tokenizes snake_case", () => {
|
|
29
|
-
expect(tokenizeIdentifier("get_user_profile")).toEqual([
|
|
30
|
-
"get",
|
|
31
|
-
"user",
|
|
32
|
-
"profile",
|
|
33
|
-
]);
|
|
34
|
-
});
|
|
35
|
-
it("tokenizes kebab-case", () => {
|
|
36
|
-
expect(tokenizeIdentifier("get-user-profile")).toEqual([
|
|
37
|
-
"get",
|
|
38
|
-
"user",
|
|
39
|
-
"profile",
|
|
40
|
-
]);
|
|
41
|
-
});
|
|
42
|
-
it("handles acronyms", () => {
|
|
43
|
-
const tokens = tokenizeIdentifier("HTMLParser");
|
|
44
|
-
expect(tokens).toContain("html");
|
|
45
|
-
expect(tokens).toContain("parser");
|
|
46
|
-
});
|
|
47
|
-
it("handles numbers", () => {
|
|
48
|
-
const tokens = tokenizeIdentifier("base64Encode");
|
|
49
|
-
expect(tokens.length).toBeGreaterThanOrEqual(2);
|
|
50
|
-
});
|
|
51
|
-
it("returns empty for empty string", () => {
|
|
52
|
-
expect(tokenizeIdentifier("")).toEqual([]);
|
|
53
|
-
});
|
|
54
|
-
it("tokenizes file paths", () => {
|
|
55
|
-
const tokens = tokenizeFilePath("src/auth/user-service.ts");
|
|
56
|
-
expect(tokens).toContain("auth");
|
|
57
|
-
expect(tokens).toContain("user");
|
|
58
|
-
expect(tokens).toContain("service");
|
|
59
|
-
});
|
|
60
|
-
it("builds token frequency", () => {
|
|
61
|
-
const freq = buildTokenFrequency(["getUserProfile", "getOrderProfile"]);
|
|
62
|
-
expect(freq.get("get")).toBe(2);
|
|
63
|
-
expect(freq.get("profile")).toBe(2);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
describe("TF-IDF Vectors (SE.2)", () => {
|
|
67
|
-
it("produces 64-dimensional vectors", () => {
|
|
68
|
-
const corpus = buildCorpus([
|
|
69
|
-
"getUserProfile",
|
|
70
|
-
"processOrder",
|
|
71
|
-
"validateInput",
|
|
72
|
-
]);
|
|
73
|
-
const vec = computeTfIdfVector("getUserProfile", corpus);
|
|
74
|
-
expect(vec.length).toBe(VECTOR_DIM);
|
|
75
|
-
expect(vec.length).toBe(64);
|
|
76
|
-
});
|
|
77
|
-
it("vectors are normalized to unit length", () => {
|
|
78
|
-
const corpus = buildCorpus(["getUserProfile", "processOrder"]);
|
|
79
|
-
const vec = computeTfIdfVector("getUserProfile", corpus);
|
|
80
|
-
let norm = 0;
|
|
81
|
-
for (let i = 0; i < vec.length; i++)
|
|
82
|
-
norm += vec[i] * vec[i];
|
|
83
|
-
expect(Math.abs(Math.sqrt(norm) - 1.0)).toBeLessThan(0.01);
|
|
84
|
-
});
|
|
85
|
-
it("similar names produce closer vectors", () => {
|
|
86
|
-
const identifiers = ["getUserProfile", "getUserSettings", "processPayment"];
|
|
87
|
-
const corpus = buildCorpus(identifiers);
|
|
88
|
-
const v1 = computeTfIdfVector("getUserProfile", corpus);
|
|
89
|
-
const v2 = computeTfIdfVector("getUserSettings", corpus);
|
|
90
|
-
const v3 = computeTfIdfVector("processPayment", corpus);
|
|
91
|
-
const sim12 = cosineSimilarity(v1, v2);
|
|
92
|
-
const sim13 = cosineSimilarity(v1, v3);
|
|
93
|
-
expect(sim12).toBeGreaterThan(sim13);
|
|
94
|
-
});
|
|
95
|
-
it("buildTfIdfVectors produces correct count", () => {
|
|
96
|
-
const vectors = buildTfIdfVectors(["a", "b", "c"]);
|
|
97
|
-
expect(vectors.size).toBe(3);
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
describe("Node2Vec (SE.3 + SE.4)", () => {
|
|
101
|
-
it("generates deterministic walks (same seed)", () => {
|
|
102
|
-
const adj = new Map([
|
|
103
|
-
["a", ["b", "c"]],
|
|
104
|
-
["b", ["a", "c"]],
|
|
105
|
-
["c", ["a", "b"]],
|
|
106
|
-
]);
|
|
107
|
-
const walks1 = generateWalks(adj, {
|
|
108
|
-
seed: 42,
|
|
109
|
-
walksPerNode: 2,
|
|
110
|
-
walkLength: 5,
|
|
111
|
-
});
|
|
112
|
-
const walks2 = generateWalks(adj, {
|
|
113
|
-
seed: 42,
|
|
114
|
-
walksPerNode: 2,
|
|
115
|
-
walkLength: 5,
|
|
116
|
-
});
|
|
117
|
-
expect(walks1).toEqual(walks2);
|
|
118
|
-
});
|
|
119
|
-
it("different seeds produce different walks", () => {
|
|
120
|
-
const adj = new Map([
|
|
121
|
-
["a", ["b", "c", "d"]],
|
|
122
|
-
["b", ["a", "c"]],
|
|
123
|
-
["c", ["a", "b"]],
|
|
124
|
-
["d", ["a"]],
|
|
125
|
-
]);
|
|
126
|
-
const walks1 = generateWalks(adj, {
|
|
127
|
-
seed: 42,
|
|
128
|
-
walksPerNode: 2,
|
|
129
|
-
walkLength: 10,
|
|
130
|
-
});
|
|
131
|
-
const walks2 = generateWalks(adj, {
|
|
132
|
-
seed: 99,
|
|
133
|
-
walksPerNode: 2,
|
|
134
|
-
walkLength: 10,
|
|
135
|
-
});
|
|
136
|
-
const flat1 = walks1.flat().join(",");
|
|
137
|
-
const flat2 = walks2.flat().join(",");
|
|
138
|
-
expect(flat1).not.toBe(flat2);
|
|
139
|
-
});
|
|
140
|
-
it("walks respect graph structure (only visit neighbors)", () => {
|
|
141
|
-
const adj = new Map([
|
|
142
|
-
["a", ["b"]],
|
|
143
|
-
["b", ["a", "c"]],
|
|
144
|
-
["c", ["b"]],
|
|
145
|
-
]);
|
|
146
|
-
const walks = generateWalks(adj, {
|
|
147
|
-
seed: 42,
|
|
148
|
-
walksPerNode: 1,
|
|
149
|
-
walkLength: 5,
|
|
150
|
-
});
|
|
151
|
-
for (const walk of walks) {
|
|
152
|
-
for (let i = 1; i < walk.length; i++) {
|
|
153
|
-
const prev = walk[i - 1];
|
|
154
|
-
const curr = walk[i];
|
|
155
|
-
expect(adj.get(prev)).toContain(curr);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
it("trainEmbeddings produces 64-dim vectors", () => {
|
|
160
|
-
const walks = [
|
|
161
|
-
["a", "b", "c", "a"],
|
|
162
|
-
["b", "c", "a", "b"],
|
|
163
|
-
];
|
|
164
|
-
const embeddings = trainEmbeddings(walks);
|
|
165
|
-
expect(embeddings.size).toBe(3);
|
|
166
|
-
for (const [_, vec] of embeddings) {
|
|
167
|
-
expect(vec.length).toBe(STRUCTURAL_DIM);
|
|
168
|
-
expect(vec.length).toBe(64);
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
it("combineEmbeddings produces 128-dim output", () => {
|
|
172
|
-
const lexical = new Float32Array(64);
|
|
173
|
-
const structural = new Float32Array(64);
|
|
174
|
-
const combined = combineEmbeddings(lexical, structural);
|
|
175
|
-
expect(combined.length).toBe(128);
|
|
176
|
-
});
|
|
177
|
-
it("buildAdjacencyFromEdges works", () => {
|
|
178
|
-
const edges = [
|
|
179
|
-
{ from_key: "a", to_key: "b" },
|
|
180
|
-
{ from_key: "b", to_key: "c" },
|
|
181
|
-
];
|
|
182
|
-
const adj = buildAdjacencyFromEdges(edges);
|
|
183
|
-
expect(adj.get("a")).toContain("b");
|
|
184
|
-
expect(adj.get("b")).toContain("a");
|
|
185
|
-
expect(adj.get("b")).toContain("c");
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
describe("Docstring Extractor (SE.6)", () => {
|
|
189
|
-
it("extracts JSDoc comment", () => {
|
|
190
|
-
const source = `/**
|
|
191
|
-
* Process a payment.
|
|
192
|
-
* @param amount - The amount
|
|
193
|
-
* @returns Receipt
|
|
194
|
-
*/
|
|
195
|
-
function processPayment(amount: number) {}`;
|
|
196
|
-
const doc = extractDocComment(source, 6);
|
|
197
|
-
expect(doc).toContain("Process a payment");
|
|
198
|
-
});
|
|
199
|
-
it("extracts doc tags", () => {
|
|
200
|
-
const doc = "Process payment. @param amount @returns Receipt @deprecated";
|
|
201
|
-
const tags = extractDocTags(doc);
|
|
202
|
-
expect(tags).toContain("param");
|
|
203
|
-
expect(tags).toContain("returns");
|
|
204
|
-
expect(tags).toContain("deprecated");
|
|
205
|
-
});
|
|
206
|
-
it("returns null for no comment", () => {
|
|
207
|
-
expect(extractDocComment("function foo() {}", 1)).toBeNull();
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
describe("Path Domain Inference (SE.7)", () => {
|
|
211
|
-
it("infers auth domain", () => {
|
|
212
|
-
const labels = inferDomain("src/auth/login.ts");
|
|
213
|
-
expect(labels[0]?.domain).toBe("authentication");
|
|
214
|
-
});
|
|
215
|
-
it("infers testing domain", () => {
|
|
216
|
-
expect(getPrimaryDomain("src/__tests__/auth.test.ts")).toBe("testing");
|
|
217
|
-
});
|
|
218
|
-
it("infers database domain", () => {
|
|
219
|
-
expect(getPrimaryDomain("src/db/migrations/001.ts")).toBe("database");
|
|
220
|
-
});
|
|
221
|
-
it("returns null for unknown paths", () => {
|
|
222
|
-
expect(getPrimaryDomain("src/foo/bar.ts")).toBeNull();
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
describe("Embedding Store (SE.8)", () => {
|
|
226
|
-
it("encodes and decodes embeddings correctly", () => {
|
|
227
|
-
const original = new Float32Array([1.0, 2.0, 3.0, -0.5]);
|
|
228
|
-
const encoded = encodeEmbedding(original);
|
|
229
|
-
const decoded = decodeEmbedding(encoded);
|
|
230
|
-
expect(decoded.length).toBe(original.length);
|
|
231
|
-
for (let i = 0; i < original.length; i++) {
|
|
232
|
-
expect(Math.abs(decoded[i] - original[i])).toBeLessThan(0.001);
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
it("cosine similarity of identical vectors is 1", () => {
|
|
236
|
-
const vec = new Float32Array([1, 0, 0, 1]);
|
|
237
|
-
expect(cosineSimilarity(vec, vec)).toBeCloseTo(1.0);
|
|
238
|
-
});
|
|
239
|
-
it("cosine similarity of orthogonal vectors is 0", () => {
|
|
240
|
-
const a = new Float32Array([1, 0, 0, 0]);
|
|
241
|
-
const b = new Float32Array([0, 1, 0, 0]);
|
|
242
|
-
expect(cosineSimilarity(a, b)).toBeCloseTo(0.0);
|
|
243
|
-
});
|
|
244
|
-
it("findSimilar returns ranked results", () => {
|
|
245
|
-
const query = new Float32Array([1, 0, 0, 0]);
|
|
246
|
-
const embeddings = new Map([
|
|
247
|
-
["close", new Float32Array([0.9, 0.1, 0, 0])],
|
|
248
|
-
["far", new Float32Array([0, 0, 0, 1])],
|
|
249
|
-
]);
|
|
250
|
-
const results = findSimilar(query, embeddings, 2);
|
|
251
|
-
expect(results[0].entityKey).toBe("close");
|
|
252
|
-
expect(results[0].similarity).toBeGreaterThan(results[1].similarity);
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
describe("Similarity Engine (SE.9)", () => {
|
|
256
|
-
it("entities with similar names AND structure rank highest", () => {
|
|
257
|
-
const queryEmb = {
|
|
258
|
-
lexical: new Float32Array(64).fill(0.1),
|
|
259
|
-
structural: new Float32Array(64).fill(0.1),
|
|
260
|
-
domain: "authentication",
|
|
261
|
-
keywords: ["get", "user"],
|
|
262
|
-
};
|
|
263
|
-
const similar = {
|
|
264
|
-
lexical: new Float32Array(64).fill(0.09),
|
|
265
|
-
structural: new Float32Array(64).fill(0.09),
|
|
266
|
-
domain: "authentication",
|
|
267
|
-
keywords: ["get", "profile"],
|
|
268
|
-
};
|
|
269
|
-
const different = {
|
|
270
|
-
lexical: new Float32Array(64).fill(-0.1),
|
|
271
|
-
structural: new Float32Array(64).fill(-0.1),
|
|
272
|
-
domain: "payments",
|
|
273
|
-
keywords: ["process", "payment"],
|
|
274
|
-
};
|
|
275
|
-
const scoreSimilar = computeSimilarity(queryEmb, similar);
|
|
276
|
-
const scoreDifferent = computeSimilarity(queryEmb, different);
|
|
277
|
-
expect(scoreSimilar).toBeGreaterThan(scoreDifferent);
|
|
278
|
-
});
|
|
279
|
-
it("findMostSimilar returns sorted results", () => {
|
|
280
|
-
const query = {
|
|
281
|
-
lexical: new Float32Array(64).fill(0.1),
|
|
282
|
-
structural: new Float32Array(64).fill(0.1),
|
|
283
|
-
domain: "auth",
|
|
284
|
-
keywords: ["login"],
|
|
285
|
-
};
|
|
286
|
-
const all = new Map([
|
|
287
|
-
["query", query],
|
|
288
|
-
["close", { ...query, domain: "auth" }],
|
|
289
|
-
[
|
|
290
|
-
"far",
|
|
291
|
-
{
|
|
292
|
-
lexical: new Float32Array(64).fill(-0.1),
|
|
293
|
-
structural: new Float32Array(64).fill(-0.1),
|
|
294
|
-
domain: "payments",
|
|
295
|
-
keywords: [],
|
|
296
|
-
},
|
|
297
|
-
],
|
|
298
|
-
]);
|
|
299
|
-
const results = findMostSimilar("query", query, all, 2);
|
|
300
|
-
expect(results.length).toBe(2);
|
|
301
|
-
expect(results[0].score).toBeGreaterThanOrEqual(results[1].score);
|
|
302
|
-
});
|
|
303
|
-
});
|
|
304
|
-
describe("Git Message Mining (SE.5)", () => {
|
|
305
|
-
it("extracts keywords from commit messages", () => {
|
|
306
|
-
const messages = [
|
|
307
|
-
"Fix authentication bug in login handler",
|
|
308
|
-
"Refactor login to use JWT tokens",
|
|
309
|
-
"Add unit tests for authentication flow",
|
|
310
|
-
];
|
|
311
|
-
const keywords = extractKeywords(messages);
|
|
312
|
-
expect(keywords).toContain("login");
|
|
313
|
-
expect(keywords).toContain("authentication");
|
|
314
|
-
expect(keywords.length).toBeGreaterThan(0);
|
|
315
|
-
expect(keywords.length).toBeLessThanOrEqual(20);
|
|
316
|
-
});
|
|
317
|
-
it("filters stopwords", () => {
|
|
318
|
-
const keywords = extractKeywords([
|
|
319
|
-
"the quick brown fox is not a good test",
|
|
320
|
-
]);
|
|
321
|
-
expect(keywords).not.toContain("the");
|
|
322
|
-
expect(keywords).not.toContain("is");
|
|
323
|
-
expect(keywords).not.toContain("not");
|
|
324
|
-
});
|
|
325
|
-
});
|
|
326
|
-
describe("Enrichment Orchestrator (SE.10)", () => {
|
|
327
|
-
it("runs full enrichment pipeline", async () => {
|
|
328
|
-
const result = await runEnrichment({
|
|
329
|
-
entities: [
|
|
330
|
-
{ key: "e1", name: "getUserProfile", file_path: "src/auth/user.ts" },
|
|
331
|
-
{
|
|
332
|
-
key: "e2",
|
|
333
|
-
name: "processPayment",
|
|
334
|
-
file_path: "src/payments/checkout.ts",
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
key: "e3",
|
|
338
|
-
name: "validateInput",
|
|
339
|
-
file_path: "src/utils/validate.ts",
|
|
340
|
-
},
|
|
341
|
-
],
|
|
342
|
-
edges: [
|
|
343
|
-
{ from_key: "e1", to_key: "e3" },
|
|
344
|
-
{ from_key: "e2", to_key: "e3" },
|
|
345
|
-
],
|
|
346
|
-
});
|
|
347
|
-
expect(result.entityCount).toBe(3);
|
|
348
|
-
expect(result.embeddings.size).toBe(3);
|
|
349
|
-
expect(result.durationMs).toBeGreaterThanOrEqual(0);
|
|
350
|
-
const e1 = result.embeddings.get("e1");
|
|
351
|
-
expect(e1.lexical.length).toBe(64);
|
|
352
|
-
expect(e1.structural.length).toBe(64);
|
|
353
|
-
expect(e1.domain).toBe("authentication");
|
|
354
|
-
});
|
|
355
|
-
it("handles empty input", async () => {
|
|
356
|
-
const result = await runEnrichment({ entities: [], edges: [] });
|
|
357
|
-
expect(result.entityCount).toBe(0);
|
|
358
|
-
expect(result.embeddings.size).toBe(0);
|
|
359
|
-
});
|
|
360
|
-
});
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck — test file
|
|
2
|
-
/**
|
|
3
|
-
* SessionBriefBuilder tests — structured session brief generation.
|
|
4
|
-
*/
|
|
5
|
-
import { describe, expect, it, vi } from "vitest";
|
|
6
|
-
import { SessionBriefBuilder } from "../intelligence/session-brief-builder.js";
|
|
7
|
-
function createMockGraph(conventions = []) {
|
|
8
|
-
return {
|
|
9
|
-
getConventions: vi.fn(() => Promise.resolve(conventions)),
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
function createMockFactStore(facts = []) {
|
|
13
|
-
return {
|
|
14
|
-
recallByScope: vi.fn(() => Promise.resolve(facts)),
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
describe("SessionBriefBuilder", () => {
|
|
18
|
-
describe("build", () => {
|
|
19
|
-
it("returns greeting with health grade when stats available", async () => {
|
|
20
|
-
const builder = new SessionBriefBuilder(null, null, { entities: 100, edges: 200, rules: 10 }, "A");
|
|
21
|
-
const brief = await builder.build();
|
|
22
|
-
expect(brief.greeting).toContain("100 entities");
|
|
23
|
-
expect(brief.greeting).toContain("scores A");
|
|
24
|
-
});
|
|
25
|
-
it("returns fallback greeting when no stats", async () => {
|
|
26
|
-
const builder = new SessionBriefBuilder(null, null, null, null);
|
|
27
|
-
const brief = await builder.build();
|
|
28
|
-
expect(brief.greeting).toContain("proxy ready");
|
|
29
|
-
});
|
|
30
|
-
it("includes inter_session_changes from resume context", async () => {
|
|
31
|
-
const builder = new SessionBriefBuilder(null, null, null, null);
|
|
32
|
-
const brief = await builder.build({
|
|
33
|
-
summary: "Last session: 10 tool calls",
|
|
34
|
-
filesModified: ["src/a.ts", "src/b.ts"],
|
|
35
|
-
incompleteEntities: [],
|
|
36
|
-
});
|
|
37
|
-
expect(brief.inter_session_changes).toEqual(["src/a.ts", "src/b.ts"]);
|
|
38
|
-
});
|
|
39
|
-
it("includes unfinished_work from resume context", async () => {
|
|
40
|
-
const builder = new SessionBriefBuilder(null, null, null, null);
|
|
41
|
-
const brief = await builder.build({
|
|
42
|
-
summary: "Last session",
|
|
43
|
-
filesModified: [],
|
|
44
|
-
incompleteEntities: ["src/wip.ts"],
|
|
45
|
-
});
|
|
46
|
-
expect(brief.unfinished_work).toEqual(["src/wip.ts"]);
|
|
47
|
-
});
|
|
48
|
-
it("omits inter_session_changes when empty", async () => {
|
|
49
|
-
const builder = new SessionBriefBuilder(null, null, null, null);
|
|
50
|
-
const brief = await builder.build({
|
|
51
|
-
summary: "Last session",
|
|
52
|
-
filesModified: [],
|
|
53
|
-
incompleteEntities: [],
|
|
54
|
-
});
|
|
55
|
-
expect(brief.inter_session_changes).toBeUndefined();
|
|
56
|
-
expect(brief.unfinished_work).toBeUndefined();
|
|
57
|
-
});
|
|
58
|
-
it("includes key_facts from fact store", async () => {
|
|
59
|
-
const factStore = createMockFactStore([
|
|
60
|
-
{
|
|
61
|
-
fact_id: "1",
|
|
62
|
-
fact_type: "semantic",
|
|
63
|
-
content: "Important fact",
|
|
64
|
-
effective_confidence: 0.9,
|
|
65
|
-
source: "auto",
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
fact_id: "2",
|
|
69
|
-
fact_type: "semantic",
|
|
70
|
-
content: "Another fact",
|
|
71
|
-
effective_confidence: 0.7,
|
|
72
|
-
source: "auto",
|
|
73
|
-
},
|
|
74
|
-
]);
|
|
75
|
-
const builder = new SessionBriefBuilder(null, factStore, null, null);
|
|
76
|
-
const brief = await builder.build();
|
|
77
|
-
expect(brief.key_facts).toHaveLength(2);
|
|
78
|
-
expect(brief.key_facts[0]).toBe("Important fact");
|
|
79
|
-
});
|
|
80
|
-
it("caps key_facts at 3", async () => {
|
|
81
|
-
const factStore = createMockFactStore([
|
|
82
|
-
{
|
|
83
|
-
fact_id: "1",
|
|
84
|
-
fact_type: "semantic",
|
|
85
|
-
content: "Fact 1",
|
|
86
|
-
effective_confidence: 0.9,
|
|
87
|
-
source: "auto",
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
fact_id: "2",
|
|
91
|
-
fact_type: "semantic",
|
|
92
|
-
content: "Fact 2",
|
|
93
|
-
effective_confidence: 0.8,
|
|
94
|
-
source: "auto",
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
fact_id: "3",
|
|
98
|
-
fact_type: "semantic",
|
|
99
|
-
content: "Fact 3",
|
|
100
|
-
effective_confidence: 0.7,
|
|
101
|
-
source: "auto",
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
fact_id: "4",
|
|
105
|
-
fact_type: "semantic",
|
|
106
|
-
content: "Fact 4",
|
|
107
|
-
effective_confidence: 0.6,
|
|
108
|
-
source: "auto",
|
|
109
|
-
},
|
|
110
|
-
]);
|
|
111
|
-
const builder = new SessionBriefBuilder(null, factStore, null, null);
|
|
112
|
-
const brief = await builder.build();
|
|
113
|
-
expect(brief.key_facts).toHaveLength(3);
|
|
114
|
-
});
|
|
115
|
-
it("includes convention_summary from graph", async () => {
|
|
116
|
-
const graph = createMockGraph([
|
|
117
|
-
{
|
|
118
|
-
name: "camelCase",
|
|
119
|
-
kind: "function",
|
|
120
|
-
frequency: 50,
|
|
121
|
-
confidence: 0.9,
|
|
122
|
-
adherence_rate: 90,
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
name: "PascalCase",
|
|
126
|
-
kind: "class",
|
|
127
|
-
frequency: 20,
|
|
128
|
-
confidence: 0.8,
|
|
129
|
-
adherence_rate: 80,
|
|
130
|
-
},
|
|
131
|
-
]);
|
|
132
|
-
const builder = new SessionBriefBuilder(graph, null, null, null);
|
|
133
|
-
const brief = await builder.build();
|
|
134
|
-
expect(brief.convention_summary).toContain("2 conventions");
|
|
135
|
-
expect(brief.convention_summary).toContain("85%");
|
|
136
|
-
});
|
|
137
|
-
it("includes intelligence_health with entity count and facts", async () => {
|
|
138
|
-
const factStore = createMockFactStore([
|
|
139
|
-
{
|
|
140
|
-
fact_id: "1",
|
|
141
|
-
fact_type: "semantic",
|
|
142
|
-
content: "Fact",
|
|
143
|
-
effective_confidence: 0.9,
|
|
144
|
-
source: "auto",
|
|
145
|
-
},
|
|
146
|
-
]);
|
|
147
|
-
const graph = createMockGraph([
|
|
148
|
-
{
|
|
149
|
-
name: "camelCase",
|
|
150
|
-
kind: "function",
|
|
151
|
-
frequency: 50,
|
|
152
|
-
confidence: 0.9,
|
|
153
|
-
adherence_rate: 90,
|
|
154
|
-
},
|
|
155
|
-
]);
|
|
156
|
-
const builder = new SessionBriefBuilder(graph, factStore, { entities: 42, edges: 100, rules: 5 }, "B");
|
|
157
|
-
const brief = await builder.build();
|
|
158
|
-
expect(brief.intelligence_health).toContain("42 entities");
|
|
159
|
-
expect(brief.intelligence_health).toContain("1 facts");
|
|
160
|
-
expect(brief.intelligence_health).toContain("1 conventions");
|
|
161
|
-
});
|
|
162
|
-
it("handles null resume context gracefully", async () => {
|
|
163
|
-
const builder = new SessionBriefBuilder(null, null, null, null);
|
|
164
|
-
const brief = await builder.build(null);
|
|
165
|
-
expect(brief.greeting).toBeDefined();
|
|
166
|
-
expect(brief.inter_session_changes).toBeUndefined();
|
|
167
|
-
expect(brief.unfinished_work).toBeUndefined();
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
describe("greeting variants", () => {
|
|
171
|
-
it("grade B includes 'could improve'", async () => {
|
|
172
|
-
const builder = new SessionBriefBuilder(null, null, { entities: 50, edges: 80, rules: 5 }, "B");
|
|
173
|
-
const brief = await builder.build();
|
|
174
|
-
expect(brief.greeting).toContain("could improve");
|
|
175
|
-
});
|
|
176
|
-
it("grade C includes 'structural issues'", async () => {
|
|
177
|
-
const builder = new SessionBriefBuilder(null, null, { entities: 50, edges: 80, rules: 5 }, "C");
|
|
178
|
-
const brief = await builder.build();
|
|
179
|
-
expect(brief.greeting).toContain("Structural issues");
|
|
180
|
-
});
|
|
181
|
-
it("grade D includes 'Warning'", async () => {
|
|
182
|
-
const builder = new SessionBriefBuilder(null, null, { entities: 50, edges: 80, rules: 5 }, "D");
|
|
183
|
-
const brief = await builder.build();
|
|
184
|
-
expect(brief.greeting).toContain("Warning");
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
});
|