seer-mcp 0.1.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/.vscode/settings.json +3 -0
- package/LICENSE +176 -0
- package/README.md +272 -0
- package/README_dev.md +199 -0
- package/dist/bundle/ci.d.ts +47 -0
- package/dist/bundle/ci.d.ts.map +1 -0
- package/dist/bundle/ci.js +113 -0
- package/dist/bundle/ci.js.map +1 -0
- package/dist/bundle/contract.d.ts +111 -0
- package/dist/bundle/contract.d.ts.map +1 -0
- package/dist/bundle/contract.js +352 -0
- package/dist/bundle/contract.js.map +1 -0
- package/dist/bundle/export.d.ts +36 -0
- package/dist/bundle/export.d.ts.map +1 -0
- package/dist/bundle/export.js +152 -0
- package/dist/bundle/export.js.map +1 -0
- package/dist/bundle/external.d.ts +66 -0
- package/dist/bundle/external.d.ts.map +1 -0
- package/dist/bundle/external.js +238 -0
- package/dist/bundle/external.js.map +1 -0
- package/dist/bundle/format.d.ts +94 -0
- package/dist/bundle/format.d.ts.map +1 -0
- package/dist/bundle/format.js +42 -0
- package/dist/bundle/format.js.map +1 -0
- package/dist/bundle/import.d.ts +49 -0
- package/dist/bundle/import.d.ts.map +1 -0
- package/dist/bundle/import.js +116 -0
- package/dist/bundle/import.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +1402 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +48 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +284 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/db/schema.d.ts +3 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +616 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/store.d.ts +1011 -0
- package/dist/db/store.d.ts.map +1 -0
- package/dist/db/store.js +3888 -0
- package/dist/db/store.js.map +1 -0
- package/dist/graph/pagerank.d.ts +9 -0
- package/dist/graph/pagerank.d.ts.map +1 -0
- package/dist/graph/pagerank.js +47 -0
- package/dist/graph/pagerank.js.map +1 -0
- package/dist/indexer/architecture.d.ts +72 -0
- package/dist/indexer/architecture.d.ts.map +1 -0
- package/dist/indexer/architecture.js +112 -0
- package/dist/indexer/architecture.js.map +1 -0
- package/dist/indexer/behavior.d.ts +75 -0
- package/dist/indexer/behavior.d.ts.map +1 -0
- package/dist/indexer/behavior.js +395 -0
- package/dist/indexer/behavior.js.map +1 -0
- package/dist/indexer/boundaries.d.ts +60 -0
- package/dist/indexer/boundaries.d.ts.map +1 -0
- package/dist/indexer/boundaries.js +366 -0
- package/dist/indexer/boundaries.js.map +1 -0
- package/dist/indexer/churn.d.ts +15 -0
- package/dist/indexer/churn.d.ts.map +1 -0
- package/dist/indexer/churn.js +49 -0
- package/dist/indexer/churn.js.map +1 -0
- package/dist/indexer/classify.d.ts +9 -0
- package/dist/indexer/classify.d.ts.map +1 -0
- package/dist/indexer/classify.js +90 -0
- package/dist/indexer/classify.js.map +1 -0
- package/dist/indexer/context.d.ts +176 -0
- package/dist/indexer/context.d.ts.map +1 -0
- package/dist/indexer/context.js +193 -0
- package/dist/indexer/context.js.map +1 -0
- package/dist/indexer/continuity.d.ts +67 -0
- package/dist/indexer/continuity.d.ts.map +1 -0
- package/dist/indexer/continuity.js +288 -0
- package/dist/indexer/continuity.js.map +1 -0
- package/dist/indexer/detectchanges.d.ts +32 -0
- package/dist/indexer/detectchanges.d.ts.map +1 -0
- package/dist/indexer/detectchanges.js +74 -0
- package/dist/indexer/detectchanges.js.map +1 -0
- package/dist/indexer/discovery.d.ts +37 -0
- package/dist/indexer/discovery.d.ts.map +1 -0
- package/dist/indexer/discovery.js +136 -0
- package/dist/indexer/discovery.js.map +1 -0
- package/dist/indexer/externaldeps.d.ts +18 -0
- package/dist/indexer/externaldeps.d.ts.map +1 -0
- package/dist/indexer/externaldeps.js +288 -0
- package/dist/indexer/externaldeps.js.map +1 -0
- package/dist/indexer/freshness.d.ts +48 -0
- package/dist/indexer/freshness.d.ts.map +1 -0
- package/dist/indexer/freshness.js +128 -0
- package/dist/indexer/freshness.js.map +1 -0
- package/dist/indexer/git.d.ts +144 -0
- package/dist/indexer/git.d.ts.map +1 -0
- package/dist/indexer/git.js +444 -0
- package/dist/indexer/git.js.map +1 -0
- package/dist/indexer/index.d.ts +145 -0
- package/dist/indexer/index.d.ts.map +1 -0
- package/dist/indexer/index.js +930 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/modules.d.ts +62 -0
- package/dist/indexer/modules.d.ts.map +1 -0
- package/dist/indexer/modules.js +293 -0
- package/dist/indexer/modules.js.map +1 -0
- package/dist/indexer/preflight.d.ts +154 -0
- package/dist/indexer/preflight.d.ts.map +1 -0
- package/dist/indexer/preflight.js +399 -0
- package/dist/indexer/preflight.js.map +1 -0
- package/dist/indexer/protoScanner.d.ts +34 -0
- package/dist/indexer/protoScanner.d.ts.map +1 -0
- package/dist/indexer/protoScanner.js +133 -0
- package/dist/indexer/protoScanner.js.map +1 -0
- package/dist/indexer/risk.d.ts +115 -0
- package/dist/indexer/risk.d.ts.map +1 -0
- package/dist/indexer/risk.js +194 -0
- package/dist/indexer/risk.js.map +1 -0
- package/dist/indexer/serviceHostScanner.d.ts +25 -0
- package/dist/indexer/serviceHostScanner.d.ts.map +1 -0
- package/dist/indexer/serviceHostScanner.js +95 -0
- package/dist/indexer/serviceHostScanner.js.map +1 -0
- package/dist/indexer/serviceLinks.d.ts +105 -0
- package/dist/indexer/serviceLinks.d.ts.map +1 -0
- package/dist/indexer/serviceLinks.js +509 -0
- package/dist/indexer/serviceLinks.js.map +1 -0
- package/dist/indexer/shapehash.d.ts +98 -0
- package/dist/indexer/shapehash.d.ts.map +1 -0
- package/dist/indexer/shapehash.js +354 -0
- package/dist/indexer/shapehash.js.map +1 -0
- package/dist/indexer/skeleton.d.ts +15 -0
- package/dist/indexer/skeleton.d.ts.map +1 -0
- package/dist/indexer/skeleton.js +136 -0
- package/dist/indexer/skeleton.js.map +1 -0
- package/dist/indexer/symbolhistory.d.ts +41 -0
- package/dist/indexer/symbolhistory.d.ts.map +1 -0
- package/dist/indexer/symbolhistory.js +124 -0
- package/dist/indexer/symbolhistory.js.map +1 -0
- package/dist/indexer/watcher.d.ts +68 -0
- package/dist/indexer/watcher.d.ts.map +1 -0
- package/dist/indexer/watcher.js +179 -0
- package/dist/indexer/watcher.js.map +1 -0
- package/dist/mcp/server.d.ts +80 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +1610 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/parser/index.d.ts +8 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +33 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/languages/cpp.d.ts +3 -0
- package/dist/parser/languages/cpp.d.ts.map +1 -0
- package/dist/parser/languages/cpp.js +350 -0
- package/dist/parser/languages/cpp.js.map +1 -0
- package/dist/parser/languages/csharp.d.ts +3 -0
- package/dist/parser/languages/csharp.d.ts.map +1 -0
- package/dist/parser/languages/csharp.js +239 -0
- package/dist/parser/languages/csharp.js.map +1 -0
- package/dist/parser/languages/go.d.ts +3 -0
- package/dist/parser/languages/go.d.ts.map +1 -0
- package/dist/parser/languages/go.js +259 -0
- package/dist/parser/languages/go.js.map +1 -0
- package/dist/parser/languages/java.d.ts +3 -0
- package/dist/parser/languages/java.d.ts.map +1 -0
- package/dist/parser/languages/java.js +391 -0
- package/dist/parser/languages/java.js.map +1 -0
- package/dist/parser/languages/python.d.ts +3 -0
- package/dist/parser/languages/python.d.ts.map +1 -0
- package/dist/parser/languages/python.js +396 -0
- package/dist/parser/languages/python.js.map +1 -0
- package/dist/parser/languages/rust.d.ts +3 -0
- package/dist/parser/languages/rust.d.ts.map +1 -0
- package/dist/parser/languages/rust.js +159 -0
- package/dist/parser/languages/rust.js.map +1 -0
- package/dist/parser/languages/typescript.d.ts +3 -0
- package/dist/parser/languages/typescript.d.ts.map +1 -0
- package/dist/parser/languages/typescript.js +1442 -0
- package/dist/parser/languages/typescript.js.map +1 -0
- package/dist/parser/parserContext.d.ts +77 -0
- package/dist/parser/parserContext.d.ts.map +1 -0
- package/dist/parser/parserContext.js +354 -0
- package/dist/parser/parserContext.js.map +1 -0
- package/dist/parser/walker.d.ts +81 -0
- package/dist/parser/walker.d.ts.map +1 -0
- package/dist/parser/walker.js +217 -0
- package/dist/parser/walker.js.map +1 -0
- package/dist/parser/worker.d.ts +66 -0
- package/dist/parser/worker.d.ts.map +1 -0
- package/dist/parser/worker.js +129 -0
- package/dist/parser/worker.js.map +1 -0
- package/dist/parser/workerpool.d.ts +107 -0
- package/dist/parser/workerpool.d.ts.map +1 -0
- package/dist/parser/workerpool.js +383 -0
- package/dist/parser/workerpool.js.map +1 -0
- package/dist/scip/format.d.ts +87 -0
- package/dist/scip/format.d.ts.map +1 -0
- package/dist/scip/format.js +31 -0
- package/dist/scip/format.js.map +1 -0
- package/dist/scip/import.d.ts +37 -0
- package/dist/scip/import.d.ts.map +1 -0
- package/dist/scip/import.js +180 -0
- package/dist/scip/import.js.map +1 -0
- package/dist/types.d.ts +392 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/docs/architecture.md +105 -0
- package/docs/benchmarks/methodology.md +134 -0
- package/docs/benchmarks/raw-results.md +71 -0
- package/docs/benchmarks.md +74 -0
- package/docs/cli.md +148 -0
- package/docs/examples/behavior-tests.md +70 -0
- package/docs/examples/change-history.md +85 -0
- package/docs/examples/pre-edit-context.md +81 -0
- package/docs/examples/service-links.md +88 -0
- package/docs/examples.md +80 -0
- package/docs/faq.md +70 -0
- package/docs/internals.md +104 -0
- package/docs/languages.md +70 -0
- package/docs/limits.md +52 -0
- package/docs/mcp.md +199 -0
- package/docs/quickstart.md +119 -0
- package/docs/testing.md +123 -0
- package/docs/tools.md +115 -0
- package/package.json +52 -0
- package/research-codebase.md +578 -0
- package/seer-cli-docs.md +326 -0
- package/seer-master-guide.md +246 -0
- package/src/bundle/ci.ts +141 -0
- package/src/bundle/contract.ts +387 -0
- package/src/bundle/export.ts +175 -0
- package/src/bundle/external.ts +285 -0
- package/src/bundle/format.ts +92 -0
- package/src/bundle/import.ts +157 -0
- package/src/cli/index.ts +1249 -0
- package/src/cli/init.ts +389 -0
- package/src/db/schema.ts +614 -0
- package/src/db/store.ts +4306 -0
- package/src/graph/pagerank.ts +53 -0
- package/src/indexer/architecture.ts +148 -0
- package/src/indexer/behavior.ts +466 -0
- package/src/indexer/boundaries.ts +374 -0
- package/src/indexer/churn.ts +58 -0
- package/src/indexer/classify.ts +96 -0
- package/src/indexer/context.ts +340 -0
- package/src/indexer/continuity.ts +322 -0
- package/src/indexer/detectchanges.ts +94 -0
- package/src/indexer/discovery.ts +176 -0
- package/src/indexer/externaldeps.ts +243 -0
- package/src/indexer/freshness.ts +166 -0
- package/src/indexer/git.ts +453 -0
- package/src/indexer/index.ts +1092 -0
- package/src/indexer/modules.ts +358 -0
- package/src/indexer/preflight.ts +548 -0
- package/src/indexer/protoScanner.ts +147 -0
- package/src/indexer/risk.ts +304 -0
- package/src/indexer/serviceHostScanner.ts +92 -0
- package/src/indexer/serviceLinks.ts +543 -0
- package/src/indexer/shapehash.ts +370 -0
- package/src/indexer/skeleton.ts +169 -0
- package/src/indexer/symbolhistory.ts +172 -0
- package/src/indexer/watcher.ts +206 -0
- package/src/mcp/server.ts +1659 -0
- package/src/parser/index.ts +37 -0
- package/src/parser/languages/cpp.ts +361 -0
- package/src/parser/languages/csharp.ts +235 -0
- package/src/parser/languages/go.ts +259 -0
- package/src/parser/languages/java.ts +382 -0
- package/src/parser/languages/python.ts +370 -0
- package/src/parser/languages/rust.ts +164 -0
- package/src/parser/languages/typescript.ts +1435 -0
- package/src/parser/parserContext.ts +392 -0
- package/src/parser/walker.ts +306 -0
- package/src/parser/worker.ts +181 -0
- package/src/parser/workerpool.ts +448 -0
- package/src/scip/format.ts +83 -0
- package/src/scip/import.ts +216 -0
- package/src/types.ts +457 -0
- package/tests/benchmark-service-links.ts +244 -0
- package/tests/bug-regressions.ts +626 -0
- package/tests/filters.ts +264 -0
- package/tests/fixtures/Counter.tsx +38 -0
- package/tests/fixtures/caller.ts +7 -0
- package/tests/fixtures/collisions.ts +23 -0
- package/tests/fixtures/local_helper.ts +5 -0
- package/tests/fixtures/overloads.java +17 -0
- package/tests/fixtures/remote_helper.ts +4 -0
- package/tests/fixtures/sample.c +15 -0
- package/tests/fixtures/sample.cpp +47 -0
- package/tests/fixtures/sample.cs +62 -0
- package/tests/fixtures/sample.go +68 -0
- package/tests/fixtures/sample.h +30 -0
- package/tests/fixtures/sample.java +85 -0
- package/tests/fixtures/sample.py +46 -0
- package/tests/fixtures/sample.rs +78 -0
- package/tests/fixtures/sample.ts +76 -0
- package/tests/fixtures-service/HttpClients.cs +30 -0
- package/tests/fixtures-service/HttpClients.java +24 -0
- package/tests/fixtures-service/billing.ts +15 -0
- package/tests/fixtures-service/docker-compose.yml +15 -0
- package/tests/fixtures-service/gateway.ts +10 -0
- package/tests/fixtures-service/get_user.ts +11 -0
- package/tests/fixtures-service/graphql_client.ts +63 -0
- package/tests/fixtures-service/graphql_server.ts +30 -0
- package/tests/fixtures-service/grpc_client.go +30 -0
- package/tests/fixtures-service/http_clients.go +23 -0
- package/tests/fixtures-service/http_clients.py +38 -0
- package/tests/fixtures-service/http_clients.ts +49 -0
- package/tests/fixtures-service/k8s/payment-service.yaml +22 -0
- package/tests/fixtures-service/k8s_calls.ts +20 -0
- package/tests/fixtures-service/messaging.ts +87 -0
- package/tests/fixtures-service/trpc_client.ts +39 -0
- package/tests/fixtures-service/trpc_server.ts +39 -0
- package/tests/fixtures-service/user_service.proto +33 -0
- package/tests/fixtures-trackcd/Cargo.toml +11 -0
- package/tests/fixtures-trackcd/SpringController.java +36 -0
- package/tests/fixtures-trackcd/auth_service.ts +19 -0
- package/tests/fixtures-trackcd/complex_module.py +50 -0
- package/tests/fixtures-trackcd/express_app.js +30 -0
- package/tests/fixtures-trackcd/fastapi_app.py +49 -0
- package/tests/fixtures-trackcd/fastify_object_routes.js +32 -0
- package/tests/fixtures-trackcd/go.mod +8 -0
- package/tests/fixtures-trackcd/package.json +15 -0
- package/tests/fixtures-trackcd/requirements.txt +4 -0
- package/tests/fixtures-trackcd/tests/auth_service.test.ts +13 -0
- package/tests/fixtures-tracke/auth/AuthService.ts +23 -0
- package/tests/fixtures-tracke/auth/crypto.ts +7 -0
- package/tests/fixtures-tracke/billing/Billing.ts +20 -0
- package/tests/fixtures-tracke/billing/Invoice.ts +10 -0
- package/tests/fixtures-tracke/billing/server.ts +17 -0
- package/tests/fixtures-tracke/package.json +7 -0
- package/tests/fixtures-tracke/tests/auth.test.ts +23 -0
- package/tests/fixtures-tracke/tests/billing.test.ts +14 -0
- package/tests/fixtures-trackf/package.json +5 -0
- package/tests/fixtures-trackf/src/auth.ts +26 -0
- package/tests/fixtures-trackf/src/handlers.ts +35 -0
- package/tests/fixtures-tracki/billing/routes.ts +12 -0
- package/tests/fixtures-tracki/gateway/client.ts +13 -0
- package/tests/git-features.ts +267 -0
- package/tests/init.ts +141 -0
- package/tests/mcp-jit.ts +130 -0
- package/tests/mcp-smoke.ts +191 -0
- package/tests/mcp-trackcd.ts +169 -0
- package/tests/mcp-tracke.ts +229 -0
- package/tests/mcp-trackf.ts +330 -0
- package/tests/mcp-trackg.ts +219 -0
- package/tests/mcp-tracki.ts +174 -0
- package/tests/mcp-watcher.ts +126 -0
- package/tests/optspec.ts +194 -0
- package/tests/parallel-index.ts +333 -0
- package/tests/parallel-read.ts +125 -0
- package/tests/parallel-recovery.ts +241 -0
- package/tests/perf-callers.ts +145 -0
- package/tests/query-parity.ts +184 -0
- package/tests/query-perf.ts +55 -0
- package/tests/scale-parallel-parity.ts +225 -0
- package/tests/scale-test.ts +523 -0
- package/tests/smoke.ts +396 -0
- package/tests/trackcd.ts +325 -0
- package/tests/tracke-collisions.ts +255 -0
- package/tests/tracke.ts +314 -0
- package/tests/trackf-bugs.ts +406 -0
- package/tests/trackf.ts +390 -0
- package/tests/trackg.ts +1372 -0
- package/tests/tracki-boundaries.ts +202 -0
- package/tests/tracki-continuity.ts +253 -0
- package/tests/tracki-contract-diff.ts +249 -0
- package/tests/tracki-external-bundles.ts +341 -0
- package/tests/tracki-preflight.ts +251 -0
- package/tests/verify-roles.ts +51 -0
- package/tests/worker-parity.ts +286 -0
- package/tests/worker-pool.ts +262 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Track I — Feature 4: Monorepo Boundaries.
|
|
3
|
+
*
|
|
4
|
+
* Verifies:
|
|
5
|
+
* - Fixture monorepo with packages/core and services/billing detected.
|
|
6
|
+
* - Each file maps to its correct boundary.
|
|
7
|
+
* - Import from services/billing into packages/core creates a boundary
|
|
8
|
+
* dependency edge.
|
|
9
|
+
* - Service link from gateway to billing is recorded as cross-boundary.
|
|
10
|
+
* - Risk + context include a `boundary` + a `boundaryCrossings` signal.
|
|
11
|
+
*
|
|
12
|
+
* Run: npx tsx tests/tracki-boundaries.ts
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import path from 'path';
|
|
16
|
+
import fs from 'fs';
|
|
17
|
+
import os from 'os';
|
|
18
|
+
import { Indexer } from '../src/indexer/index';
|
|
19
|
+
import { Store } from '../src/db/store';
|
|
20
|
+
import { computeRisk } from '../src/indexer/risk';
|
|
21
|
+
import { buildContext } from '../src/indexer/context';
|
|
22
|
+
|
|
23
|
+
const TMP = path.join(os.tmpdir(), `seer-tracki-bnd-${Date.now()}`);
|
|
24
|
+
|
|
25
|
+
let passed = 0;
|
|
26
|
+
let failed = 0;
|
|
27
|
+
function assert(cond: boolean, msg: string): void {
|
|
28
|
+
if (cond) { console.log(` ✓ ${msg}`); passed++; }
|
|
29
|
+
else { console.error(` ✗ ${msg}`); failed++; }
|
|
30
|
+
}
|
|
31
|
+
function assertEq<T>(actual: T, expected: T, msg: string): void {
|
|
32
|
+
assert(actual === expected,
|
|
33
|
+
`${msg} (got ${JSON.stringify(actual)}, expected ${JSON.stringify(expected)})`);
|
|
34
|
+
}
|
|
35
|
+
function cleanup(): void {
|
|
36
|
+
try { fs.rmSync(TMP, { recursive: true, force: true }); } catch { /* */ }
|
|
37
|
+
}
|
|
38
|
+
function write(rel: string, content: string): void {
|
|
39
|
+
const full = path.join(TMP, rel);
|
|
40
|
+
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
41
|
+
fs.writeFileSync(full, content, 'utf8');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function main(): Promise<void> {
|
|
45
|
+
console.log('\nSeer Track I — Feature 4: Monorepo Boundaries');
|
|
46
|
+
console.log('==============================================\n');
|
|
47
|
+
cleanup();
|
|
48
|
+
fs.mkdirSync(TMP, { recursive: true });
|
|
49
|
+
|
|
50
|
+
// ── Build the fixture monorepo ──────────────────────────────────────────
|
|
51
|
+
// Repo root package.json declares workspaces — workspace-root boundary.
|
|
52
|
+
write('package.json', JSON.stringify({
|
|
53
|
+
name: 'my-monorepo', version: '1.0.0', private: true,
|
|
54
|
+
workspaces: ['packages/*', 'services/*'],
|
|
55
|
+
}, null, 2));
|
|
56
|
+
// packages/core — utility package with package.json
|
|
57
|
+
write('packages/core/package.json', JSON.stringify({
|
|
58
|
+
name: '@my/core', version: '0.1.0',
|
|
59
|
+
}, null, 2));
|
|
60
|
+
write('packages/core/src/utils.ts', `
|
|
61
|
+
export function makeId(seed: number): string {
|
|
62
|
+
return 'id-' + seed;
|
|
63
|
+
}
|
|
64
|
+
export function logEvent(name: string): void {
|
|
65
|
+
console.log(name);
|
|
66
|
+
}
|
|
67
|
+
`.trimStart());
|
|
68
|
+
// services/billing — service with package.json that imports from core
|
|
69
|
+
write('services/billing/package.json', JSON.stringify({
|
|
70
|
+
name: 'billing-service', version: '0.1.0',
|
|
71
|
+
}, null, 2));
|
|
72
|
+
write('services/billing/src/charge.ts', `
|
|
73
|
+
import { makeId } from '../../../packages/core/src/utils';
|
|
74
|
+
declare const app: any;
|
|
75
|
+
|
|
76
|
+
export function chargeHandler(req: any, res: any): unknown {
|
|
77
|
+
const id = makeId(req.body.amount);
|
|
78
|
+
return res.send({ id, charged: true });
|
|
79
|
+
}
|
|
80
|
+
app.post('/api/charge', chargeHandler);
|
|
81
|
+
`.trimStart());
|
|
82
|
+
// services/gateway — calls into billing (cross-boundary service link)
|
|
83
|
+
write('services/gateway/package.json', JSON.stringify({
|
|
84
|
+
name: 'gateway-service', version: '0.1.0',
|
|
85
|
+
}, null, 2));
|
|
86
|
+
write('services/gateway/src/client.ts', `
|
|
87
|
+
declare const fetch: any;
|
|
88
|
+
export async function processPayment(amount: number): Promise<unknown> {
|
|
89
|
+
return await fetch('/api/charge', {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
body: JSON.stringify({ amount }),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
`.trimStart());
|
|
95
|
+
// apps/cli — convention fallback (no package.json under apps directly).
|
|
96
|
+
// We make it manifest-less to exercise the convention path.
|
|
97
|
+
write('apps/cli/src/main.ts', `
|
|
98
|
+
export function entrypoint(): void { console.log('hi'); }
|
|
99
|
+
`.trimStart());
|
|
100
|
+
|
|
101
|
+
// ── Index it ───────────────────────────────────────────────────────────
|
|
102
|
+
const dbPath = path.join(TMP, 'graph.db');
|
|
103
|
+
const store = new Store(dbPath);
|
|
104
|
+
try {
|
|
105
|
+
const idx = new Indexer(store);
|
|
106
|
+
await idx.indexDirectory(TMP, { quiet: true });
|
|
107
|
+
|
|
108
|
+
// ── Boundaries detected ───────────────────────────────────────────────
|
|
109
|
+
console.log('── Boundary detection ──');
|
|
110
|
+
const boundaries = store.listBoundaries(100);
|
|
111
|
+
console.log(` detected ${boundaries.length} boundaries:`);
|
|
112
|
+
for (const b of boundaries) {
|
|
113
|
+
console.log(` [${b.kind}] ${b.label} (${b.rootRelPath}) — ${b.sizeFiles} file(s)`);
|
|
114
|
+
}
|
|
115
|
+
assert(boundaries.length >= 4,
|
|
116
|
+
`at least 4 boundaries detected (root + core + billing + gateway): got ${boundaries.length}`);
|
|
117
|
+
|
|
118
|
+
const labels = boundaries.map(b => b.label);
|
|
119
|
+
assert(labels.includes('core'), 'core boundary detected');
|
|
120
|
+
assert(labels.includes('billing-service'),
|
|
121
|
+
'billing-service boundary detected from package.json:name');
|
|
122
|
+
assert(labels.includes('gateway-service'),
|
|
123
|
+
'gateway-service boundary detected from package.json:name');
|
|
124
|
+
assert(labels.includes('cli'),
|
|
125
|
+
'cli boundary detected via apps/* convention fallback');
|
|
126
|
+
|
|
127
|
+
const billingBnd = boundaries.find(b => b.label === 'billing-service');
|
|
128
|
+
const coreBnd = boundaries.find(b => b.label === 'core');
|
|
129
|
+
const gatewayBnd = boundaries.find(b => b.label === 'gateway-service');
|
|
130
|
+
assert(billingBnd?.kind === 'package', 'billing detected via manifest -> kind=package');
|
|
131
|
+
assert(coreBnd?.kind === 'package', 'core detected via manifest -> kind=package');
|
|
132
|
+
assert(gatewayBnd?.kind === 'package',
|
|
133
|
+
`gateway detected via package.json (got kind=${gatewayBnd?.kind})`);
|
|
134
|
+
|
|
135
|
+
// ── File→boundary mapping ─────────────────────────────────────────────
|
|
136
|
+
console.log('\n── File→boundary mapping ──');
|
|
137
|
+
const files = store.listFiles();
|
|
138
|
+
const findFile = (rel: string) =>
|
|
139
|
+
files.find(f => f.relPath.replace(/\\/g, '/').endsWith(rel));
|
|
140
|
+
const utilsFile = findFile('packages/core/src/utils.ts');
|
|
141
|
+
const chargeFile = findFile('services/billing/src/charge.ts');
|
|
142
|
+
const clientFile = findFile('services/gateway/src/client.ts');
|
|
143
|
+
assert(utilsFile != null, 'packages/core/src/utils.ts indexed');
|
|
144
|
+
assert(chargeFile != null, 'services/billing/src/charge.ts indexed');
|
|
145
|
+
assert(clientFile != null, 'services/gateway/src/client.ts indexed');
|
|
146
|
+
if (utilsFile && chargeFile && clientFile) {
|
|
147
|
+
const utilsBoundary = store.boundaryForFile(utilsFile.id);
|
|
148
|
+
const chargeBoundary = store.boundaryForFile(chargeFile.id);
|
|
149
|
+
const clientBoundary = store.boundaryForFile(clientFile.id);
|
|
150
|
+
assert(utilsBoundary?.label === 'core', 'utils.ts → core boundary');
|
|
151
|
+
assert(chargeBoundary?.label === 'billing-service', 'charge.ts → billing boundary');
|
|
152
|
+
assert(clientBoundary?.label === 'gateway-service', 'client.ts → gateway boundary');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ── Boundary edges: billing → core (via import) ──────────────────────
|
|
156
|
+
console.log('\n── Boundary dependency edges ──');
|
|
157
|
+
if (billingBnd && coreBnd) {
|
|
158
|
+
const out = store.boundaryDependencies(billingBnd.id, { direction: 'out', limit: 50 });
|
|
159
|
+
console.log(` billing → ${out.length} boundaries`);
|
|
160
|
+
for (const d of out) console.log(` ${d.kind}=${d.weight} → ${d.label}`);
|
|
161
|
+
const importEdge = out.find(d => d.label === 'core' && d.kind === 'import');
|
|
162
|
+
assert(importEdge != null,
|
|
163
|
+
'billing → core import edge recorded (billing imports core/utils)');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ── Risk: cross-boundary signal surfaces on chargeHandler ────────────
|
|
167
|
+
console.log('\n── Risk: boundary crossing ──');
|
|
168
|
+
const r = computeRisk(store, 'chargeHandler');
|
|
169
|
+
assert(r != null, 'risk(chargeHandler) returned a result');
|
|
170
|
+
if (r) {
|
|
171
|
+
assert(r.boundary != null, 'risk.boundary populated');
|
|
172
|
+
assertEq(r.boundary?.label, 'billing-service',
|
|
173
|
+
'risk.boundary is billing-service for chargeHandler');
|
|
174
|
+
assert(r.signals.boundaryCrossings >= 0,
|
|
175
|
+
'risk.signals.boundaryCrossings is present');
|
|
176
|
+
const sig = r.signalContributions.find(c => c.signal === 'boundaryCrossings');
|
|
177
|
+
assert(sig != null,
|
|
178
|
+
'risk.signalContributions includes boundaryCrossings');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ── Context: boundary populated ──────────────────────────────────────
|
|
182
|
+
console.log('\n── Context: boundary populated ──');
|
|
183
|
+
const ctx = buildContext(store, 'chargeHandler');
|
|
184
|
+
assert(ctx != null, 'context(chargeHandler) returned');
|
|
185
|
+
if (ctx) {
|
|
186
|
+
assert(ctx.boundary != null, 'context.boundary populated');
|
|
187
|
+
assertEq(ctx.boundary?.label, 'billing-service',
|
|
188
|
+
'context.boundary.label = billing-service');
|
|
189
|
+
}
|
|
190
|
+
} finally { store.close(); }
|
|
191
|
+
|
|
192
|
+
console.log('\n────────────────────────────');
|
|
193
|
+
console.log(`Passed: ${passed} Failed: ${failed}`);
|
|
194
|
+
cleanup();
|
|
195
|
+
if (failed > 0) process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
main().catch(err => {
|
|
199
|
+
console.error(err);
|
|
200
|
+
cleanup();
|
|
201
|
+
process.exit(1);
|
|
202
|
+
});
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Track I — Feature 5: Symbol Rename/Move Continuity.
|
|
3
|
+
*
|
|
4
|
+
* Verifies:
|
|
5
|
+
* - Renaming `validateToken` → `verifyToken` (same body) produces a
|
|
6
|
+
* continuity candidate that links the two with high confidence.
|
|
7
|
+
* - Two distinct similar functions do NOT collapse: when names share a
|
|
8
|
+
* similar shape but bodies differ, continuity confidence stays low or
|
|
9
|
+
* the candidate is skipped.
|
|
10
|
+
* - A file move with same body yields continuity evidence.
|
|
11
|
+
* - Existing symbol_history rows are unaffected (additive only).
|
|
12
|
+
*
|
|
13
|
+
* Run: npx tsx tests/tracki-continuity.ts
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import path from 'path';
|
|
17
|
+
import fs from 'fs';
|
|
18
|
+
import os from 'os';
|
|
19
|
+
import { Indexer } from '../src/indexer/index';
|
|
20
|
+
import { Store } from '../src/db/store';
|
|
21
|
+
import { buildContinuity, getContinuityForSymbol } from '../src/indexer/continuity';
|
|
22
|
+
|
|
23
|
+
const TMP = path.join(os.tmpdir(), `seer-tracki-cont-${Date.now()}`);
|
|
24
|
+
|
|
25
|
+
let passed = 0;
|
|
26
|
+
let failed = 0;
|
|
27
|
+
function assert(cond: boolean, msg: string): void {
|
|
28
|
+
if (cond) { console.log(` ✓ ${msg}`); passed++; }
|
|
29
|
+
else { console.error(` ✗ ${msg}`); failed++; }
|
|
30
|
+
}
|
|
31
|
+
function assertEq<T>(actual: T, expected: T, msg: string): void {
|
|
32
|
+
assert(actual === expected,
|
|
33
|
+
`${msg} (got ${JSON.stringify(actual)}, expected ${JSON.stringify(expected)})`);
|
|
34
|
+
}
|
|
35
|
+
function cleanup(): void {
|
|
36
|
+
try { fs.rmSync(TMP, { recursive: true, force: true }); } catch { /* */ }
|
|
37
|
+
}
|
|
38
|
+
function write(rel: string, content: string): void {
|
|
39
|
+
const full = path.join(TMP, rel);
|
|
40
|
+
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
41
|
+
fs.writeFileSync(full, content, 'utf8');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function main(): Promise<void> {
|
|
45
|
+
console.log('\nSeer Track I — Feature 5: Symbol Rename/Move Continuity');
|
|
46
|
+
console.log('========================================================\n');
|
|
47
|
+
cleanup();
|
|
48
|
+
fs.mkdirSync(TMP, { recursive: true });
|
|
49
|
+
|
|
50
|
+
// ── Fixture 1: function renamed within the same file ───────────────────
|
|
51
|
+
console.log('── Fixture 1: function renamed inside the same file ──');
|
|
52
|
+
// We capture two snapshots in the same DB so that BOTH the pre-rename
|
|
53
|
+
// (validateToken) and post-rename (verifyToken) symbol rows coexist —
|
|
54
|
+
// which is the snapshot continuity inspects (it doesn't need git history
|
|
55
|
+
// for the heuristic; shape_hash equality is enough).
|
|
56
|
+
write('auth.ts', `
|
|
57
|
+
export function validateToken(token: string): boolean {
|
|
58
|
+
if (!token) return false;
|
|
59
|
+
return token.length > 8;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Same body, different name — direct rename simulation.
|
|
63
|
+
export function verifyToken(other: string): boolean {
|
|
64
|
+
if (!other) return false;
|
|
65
|
+
return other.length > 8;
|
|
66
|
+
}
|
|
67
|
+
`.trimStart());
|
|
68
|
+
|
|
69
|
+
const dbPath = path.join(TMP, 'graph.db');
|
|
70
|
+
let store = new Store(dbPath);
|
|
71
|
+
try {
|
|
72
|
+
const idx = new Indexer(store);
|
|
73
|
+
await idx.indexDirectory(TMP, { quiet: true });
|
|
74
|
+
|
|
75
|
+
// Force a continuity pass that considers all symbols.
|
|
76
|
+
const r = buildContinuity(store, {
|
|
77
|
+
historyThreshold: 1, includeAllSymbols: true,
|
|
78
|
+
});
|
|
79
|
+
console.log(` continuity: considered=${r.candidatesConsidered}, inserted=${r.inserted}, skipped=${r.skipped}`);
|
|
80
|
+
assert(r.inserted >= 1, 'continuity inserted ≥1 candidate');
|
|
81
|
+
|
|
82
|
+
const verifyDef = store.getDefinition('verifyToken');
|
|
83
|
+
assert(verifyDef.length === 1, 'verifyToken found');
|
|
84
|
+
const valDef = store.getDefinition('validateToken');
|
|
85
|
+
assert(valDef.length === 1, 'validateToken found');
|
|
86
|
+
|
|
87
|
+
if (verifyDef.length === 1) {
|
|
88
|
+
const cont = getContinuityForSymbol(store, verifyDef[0].id);
|
|
89
|
+
console.log(` verifyToken continuity candidates: ${cont.length}`);
|
|
90
|
+
for (const c of cont) {
|
|
91
|
+
console.log(` ← ${c.previousName.padEnd(20)} conf=${c.confidence.toFixed(2)} ${c.matchReasons.join(', ')}`);
|
|
92
|
+
}
|
|
93
|
+
assert(cont.length >= 1, 'verifyToken has at least one continuity candidate');
|
|
94
|
+
const linked = cont.find(c => c.previousName === 'validateToken');
|
|
95
|
+
assert(linked != null, 'verifyToken → validateToken candidate present');
|
|
96
|
+
if (linked) {
|
|
97
|
+
assert(linked.confidence >= 0.8,
|
|
98
|
+
`verifyToken → validateToken confidence ≥ 0.8 (got ${linked.confidence})`);
|
|
99
|
+
assert(linked.matchReasons.includes('shape_hash_exact'),
|
|
100
|
+
'reasons include shape_hash_exact');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
} finally { store.close(); }
|
|
104
|
+
|
|
105
|
+
// ── Fixture 2: ambiguous match (different body) → low or no candidate ──
|
|
106
|
+
console.log('\n── Fixture 2: ambiguous shape mismatch ──');
|
|
107
|
+
cleanup();
|
|
108
|
+
fs.mkdirSync(TMP, { recursive: true });
|
|
109
|
+
write('ambiguous.ts', `
|
|
110
|
+
export function loadOne(): string {
|
|
111
|
+
console.log('one');
|
|
112
|
+
return 'one';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function loadTwo(): string {
|
|
116
|
+
// Totally different body — many statements
|
|
117
|
+
let acc = 0;
|
|
118
|
+
for (let i = 0; i < 100; i++) {
|
|
119
|
+
acc += i * 2;
|
|
120
|
+
if (acc > 1000) { break; }
|
|
121
|
+
}
|
|
122
|
+
return String(acc);
|
|
123
|
+
}
|
|
124
|
+
`.trimStart());
|
|
125
|
+
|
|
126
|
+
store = new Store(dbPath);
|
|
127
|
+
try {
|
|
128
|
+
const idx = new Indexer(store);
|
|
129
|
+
await idx.indexDirectory(TMP, { quiet: true });
|
|
130
|
+
buildContinuity(store, { historyThreshold: 1, includeAllSymbols: true });
|
|
131
|
+
const oneDef = store.getDefinition('loadOne');
|
|
132
|
+
const twoDef = store.getDefinition('loadTwo');
|
|
133
|
+
assert(oneDef.length === 1, 'loadOne found');
|
|
134
|
+
assert(twoDef.length === 1, 'loadTwo found');
|
|
135
|
+
if (oneDef.length === 1 && twoDef.length === 1) {
|
|
136
|
+
const cOne = getContinuityForSymbol(store, oneDef[0].id);
|
|
137
|
+
const cTwo = getContinuityForSymbol(store, twoDef[0].id);
|
|
138
|
+
// Even if a candidate was inserted, the confidence must reflect
|
|
139
|
+
// ambiguity — never pretend it's certain.
|
|
140
|
+
for (const c of [...cOne, ...cTwo]) {
|
|
141
|
+
assert(c.confidence < 0.9,
|
|
142
|
+
`ambiguous candidate confidence is < 0.9 (got ${c.confidence})`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
} finally { store.close(); }
|
|
146
|
+
|
|
147
|
+
// ── Fixture 3: file move with same body ────────────────────────────────
|
|
148
|
+
console.log('\n── Fixture 3: file move (same body) ──');
|
|
149
|
+
cleanup();
|
|
150
|
+
fs.mkdirSync(TMP, { recursive: true });
|
|
151
|
+
write('old-location/utils.ts', `
|
|
152
|
+
export function shared(seed: number): string {
|
|
153
|
+
const a = seed * 2;
|
|
154
|
+
const b = a + 1;
|
|
155
|
+
return String(b);
|
|
156
|
+
}
|
|
157
|
+
`.trimStart());
|
|
158
|
+
write('new-location/utils.ts', `
|
|
159
|
+
export function sharedMoved(seed: number): string {
|
|
160
|
+
const a = seed * 2;
|
|
161
|
+
const b = a + 1;
|
|
162
|
+
return String(b);
|
|
163
|
+
}
|
|
164
|
+
`.trimStart());
|
|
165
|
+
|
|
166
|
+
store = new Store(dbPath);
|
|
167
|
+
try {
|
|
168
|
+
const idx = new Indexer(store);
|
|
169
|
+
await idx.indexDirectory(TMP, { quiet: true });
|
|
170
|
+
buildContinuity(store, { historyThreshold: 1, includeAllSymbols: true });
|
|
171
|
+
const sharedMoved = store.getDefinition('sharedMoved');
|
|
172
|
+
assert(sharedMoved.length === 1, 'sharedMoved found');
|
|
173
|
+
if (sharedMoved.length === 1) {
|
|
174
|
+
const cont = getContinuityForSymbol(store, sharedMoved[0].id);
|
|
175
|
+
assert(cont.length >= 1, 'sharedMoved has a continuity candidate (file move)');
|
|
176
|
+
const linked = cont.find(c => c.previousName === 'shared');
|
|
177
|
+
assert(linked != null, 'sharedMoved → shared candidate present (file move)');
|
|
178
|
+
if (linked) {
|
|
179
|
+
assert(linked.confidence >= 0.75,
|
|
180
|
+
`file-move continuity confidence ≥ 0.75 (got ${linked.confidence})`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
} finally { store.close(); }
|
|
184
|
+
|
|
185
|
+
// ── Fixture 4: common shape collision must NOT invent high-conf renames ──
|
|
186
|
+
// Many structurally-identical functions with UNRELATED names in different
|
|
187
|
+
// files share one shape_hash. That is boilerplate, not a rename — continuity
|
|
188
|
+
// must refuse to assert a high-confidence link with no corroboration.
|
|
189
|
+
console.log('\n── Fixture 4: ambiguous shape bucket (boilerplate) ──');
|
|
190
|
+
cleanup();
|
|
191
|
+
fs.mkdirSync(TMP, { recursive: true });
|
|
192
|
+
const body = (name: string): string =>
|
|
193
|
+
`export function ${name}(): number {\n const a = 1;\n const b = 2;\n return a + b;\n}\n`;
|
|
194
|
+
// Names chosen to share no 4-char prefix/suffix with each other.
|
|
195
|
+
write('f1.ts', body('alpha'));
|
|
196
|
+
write('f2.ts', body('zeta'));
|
|
197
|
+
write('f3.ts', body('omega'));
|
|
198
|
+
write('f4.ts', body('kappa'));
|
|
199
|
+
store = new Store(dbPath);
|
|
200
|
+
try {
|
|
201
|
+
const idx = new Indexer(store);
|
|
202
|
+
await idx.indexDirectory(TMP, { quiet: true });
|
|
203
|
+
const r = buildContinuity(store, { historyThreshold: 1, includeAllSymbols: true });
|
|
204
|
+
console.log(` continuity: considered=${r.candidatesConsidered}, inserted=${r.inserted}, skipped=${r.skipped}`);
|
|
205
|
+
for (const nm of ['alpha', 'zeta', 'omega', 'kappa']) {
|
|
206
|
+
const def = store.getDefinition(nm);
|
|
207
|
+
if (def.length !== 1) { assert(false, `${nm} found`); continue; }
|
|
208
|
+
const cont = getContinuityForSymbol(store, def[0].id);
|
|
209
|
+
for (const c of cont) {
|
|
210
|
+
console.log(` ${nm} ← ${c.previousName} conf=${c.confidence.toFixed(2)} ${c.matchReasons.join(',')}`);
|
|
211
|
+
}
|
|
212
|
+
// The honesty contract: a shared boilerplate shape with unrelated names
|
|
213
|
+
// and different scopes must never yield a high-confidence rename.
|
|
214
|
+
const highConf = cont.find(c => c.confidence >= 0.8);
|
|
215
|
+
assert(highConf == null,
|
|
216
|
+
`${nm}: no high-confidence rename from a common shape (got ${cont.map(c => c.confidence).join(',') || 'none'})`);
|
|
217
|
+
}
|
|
218
|
+
} finally { store.close(); }
|
|
219
|
+
|
|
220
|
+
// ── Honesty check: schema continuity record exists with reasons array ──
|
|
221
|
+
console.log('\n── Schema check ──');
|
|
222
|
+
cleanup();
|
|
223
|
+
fs.mkdirSync(TMP, { recursive: true });
|
|
224
|
+
write('a.ts', 'export function alpha(): number { return 1 + 2 + 3; }\n');
|
|
225
|
+
write('b.ts', 'export function alpha2(): number { return 1 + 2 + 3; }\n');
|
|
226
|
+
store = new Store(dbPath);
|
|
227
|
+
try {
|
|
228
|
+
const idx = new Indexer(store);
|
|
229
|
+
await idx.indexDirectory(TMP, { quiet: true });
|
|
230
|
+
buildContinuity(store, { historyThreshold: 1, includeAllSymbols: true });
|
|
231
|
+
const cols = (store.rawDb().prepare(
|
|
232
|
+
"PRAGMA table_info('symbol_history_continuity')",
|
|
233
|
+
).all() as Array<{ name: string }>).map(r => r.name);
|
|
234
|
+
for (const c of [
|
|
235
|
+
'id', 'symbol_id', 'symbol_key', 'previous_symbol_key',
|
|
236
|
+
'previous_name', 'previous_file', 'confidence',
|
|
237
|
+
'match_reasons', 'recorded_at',
|
|
238
|
+
]) {
|
|
239
|
+
assert(cols.includes(c), `symbol_history_continuity column ${c} exists`);
|
|
240
|
+
}
|
|
241
|
+
} finally { store.close(); }
|
|
242
|
+
|
|
243
|
+
console.log('\n────────────────────────────');
|
|
244
|
+
console.log(`Passed: ${passed} Failed: ${failed}`);
|
|
245
|
+
cleanup();
|
|
246
|
+
if (failed > 0) process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
main().catch(err => {
|
|
250
|
+
console.error(err);
|
|
251
|
+
cleanup();
|
|
252
|
+
process.exit(1);
|
|
253
|
+
});
|