pi-lens 2.2.9 → 3.0.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/CHANGELOG.md +198 -0
- package/README.md +709 -519
- package/clients/__tests__/file-time.test.js +216 -0
- package/clients/__tests__/file-time.test.ts +276 -0
- package/clients/__tests__/format-service.test.js +245 -0
- package/clients/__tests__/format-service.test.ts +339 -0
- package/clients/__tests__/formatters.test.js +271 -0
- package/clients/__tests__/formatters.test.ts +401 -0
- package/clients/amain-types.js +164 -0
- package/clients/amain-types.ts +165 -0
- package/clients/architect-client.js +56 -12
- package/clients/architect-client.ts +81 -16
- package/clients/ast-grep-client.js +2 -2
- package/clients/ast-grep-client.ts +14 -39
- package/clients/ast-grep-parser.ts +1 -1
- package/clients/ast-grep-rule-manager.js +8 -0
- package/clients/ast-grep-rule-manager.ts +10 -1
- package/clients/ast-grep-types.js +9 -0
- package/clients/ast-grep-types.ts +106 -0
- package/clients/auto-loop.js +10 -0
- package/clients/auto-loop.ts +14 -1
- package/clients/biome-client.js +81 -19
- package/clients/biome-client.ts +103 -22
- package/clients/bus/bus.js +191 -0
- package/clients/bus/bus.ts +251 -0
- package/clients/bus/events.js +214 -0
- package/clients/bus/events.ts +279 -0
- package/clients/bus/index.js +8 -0
- package/clients/bus/index.ts +9 -0
- package/clients/bus/integration.js +158 -0
- package/clients/bus/integration.ts +214 -0
- package/clients/complexity-client.js +13 -7
- package/clients/complexity-client.ts +13 -7
- package/clients/config-validator.js +465 -0
- package/clients/config-validator.ts +558 -0
- package/clients/dependency-checker.js +4 -10
- package/clients/dependency-checker.ts +4 -10
- package/clients/dispatch/__tests__/autofix-integration.test.js +245 -0
- package/clients/dispatch/__tests__/autofix-integration.test.ts +300 -0
- package/clients/dispatch/__tests__/runner-registration.test.js +236 -0
- package/clients/dispatch/__tests__/runner-registration.test.ts +282 -0
- package/clients/dispatch/bus-dispatcher.js +177 -0
- package/clients/dispatch/bus-dispatcher.ts +251 -0
- package/clients/dispatch/dispatcher.edge.test.js +82 -0
- package/clients/dispatch/dispatcher.edge.test.ts +100 -0
- package/clients/dispatch/dispatcher.format.test.js +46 -0
- package/clients/dispatch/dispatcher.format.test.ts +58 -0
- package/clients/dispatch/dispatcher.inline.test.js +74 -0
- package/clients/dispatch/dispatcher.inline.test.ts +93 -0
- package/clients/dispatch/dispatcher.js +19 -53
- package/clients/dispatch/dispatcher.ts +20 -67
- package/clients/dispatch/plan.js +9 -4
- package/clients/dispatch/plan.ts +9 -4
- package/clients/dispatch/runners/architect.js +21 -7
- package/clients/dispatch/runners/architect.test.js +138 -0
- package/clients/dispatch/runners/architect.test.ts +162 -0
- package/clients/dispatch/runners/architect.ts +22 -7
- package/clients/dispatch/runners/ast-grep-napi.js +462 -0
- package/clients/dispatch/runners/ast-grep-napi.test.js +111 -0
- package/clients/dispatch/runners/ast-grep-napi.test.ts +133 -0
- package/clients/dispatch/runners/ast-grep-napi.ts +506 -0
- package/clients/dispatch/runners/ast-grep.js +62 -19
- package/clients/dispatch/runners/ast-grep.ts +70 -18
- package/clients/dispatch/runners/biome.js +29 -53
- package/clients/dispatch/runners/biome.ts +29 -63
- package/clients/dispatch/runners/config-validation.js +67 -0
- package/clients/dispatch/runners/config-validation.ts +82 -0
- package/clients/dispatch/runners/go-vet.js +4 -28
- package/clients/dispatch/runners/go-vet.ts +4 -32
- package/clients/dispatch/runners/index.js +30 -10
- package/clients/dispatch/runners/index.ts +30 -10
- package/clients/dispatch/runners/oxlint.js +141 -0
- package/clients/dispatch/runners/oxlint.test.js +230 -0
- package/clients/dispatch/runners/oxlint.test.ts +303 -0
- package/clients/dispatch/runners/oxlint.ts +175 -0
- package/clients/dispatch/runners/pyright.js +40 -70
- package/clients/dispatch/runners/pyright.test.js +16 -2
- package/clients/dispatch/runners/pyright.test.ts +14 -2
- package/clients/dispatch/runners/pyright.ts +48 -91
- package/clients/dispatch/runners/python-slop.js +97 -0
- package/clients/dispatch/runners/python-slop.test.js +203 -0
- package/clients/dispatch/runners/python-slop.test.ts +298 -0
- package/clients/dispatch/runners/python-slop.ts +124 -0
- package/clients/dispatch/runners/ruff.js +18 -71
- package/clients/dispatch/runners/ruff.ts +19 -79
- package/clients/dispatch/runners/rust-clippy.js +28 -32
- package/clients/dispatch/runners/rust-clippy.ts +29 -31
- package/clients/dispatch/runners/scan_codebase.test.js +89 -0
- package/clients/dispatch/runners/scan_codebase.test.ts +105 -0
- package/clients/dispatch/runners/shellcheck.js +147 -0
- package/clients/dispatch/runners/shellcheck.test.js +98 -0
- package/clients/dispatch/runners/shellcheck.test.ts +129 -0
- package/clients/dispatch/runners/shellcheck.ts +188 -0
- package/clients/dispatch/runners/similarity.js +230 -0
- package/clients/dispatch/runners/similarity.ts +339 -0
- package/clients/dispatch/runners/spellcheck.js +106 -0
- package/clients/dispatch/runners/spellcheck.test.js +158 -0
- package/clients/dispatch/runners/spellcheck.test.ts +214 -0
- package/clients/dispatch/runners/spellcheck.ts +136 -0
- package/clients/dispatch/runners/tree-sitter.js +107 -0
- package/clients/dispatch/runners/tree-sitter.ts +135 -0
- package/clients/dispatch/runners/ts-lsp.js +104 -33
- package/clients/dispatch/runners/ts-lsp.ts +120 -38
- package/clients/dispatch/runners/ts-slop.js +113 -0
- package/clients/dispatch/runners/ts-slop.test.js +180 -0
- package/clients/dispatch/runners/ts-slop.test.ts +230 -0
- package/clients/dispatch/runners/ts-slop.ts +142 -0
- package/clients/dispatch/runners/utils/diagnostic-parsers.js +134 -0
- package/clients/dispatch/runners/utils/diagnostic-parsers.ts +186 -0
- package/clients/dispatch/runners/utils/runner-helpers.js +115 -0
- package/clients/dispatch/runners/utils/runner-helpers.ts +167 -0
- package/clients/dispatch/runners/utils.js +2 -4
- package/clients/dispatch/runners/utils.ts +2 -4
- package/clients/dispatch/types.ts +1 -1
- package/clients/dispatch/utils/format-utils.js +49 -0
- package/clients/dispatch/utils/format-utils.ts +60 -0
- package/clients/dogfood.test.js +201 -0
- package/clients/dogfood.test.ts +269 -0
- package/clients/file-time.js +152 -0
- package/clients/file-time.ts +208 -0
- package/clients/file-utils.js +40 -0
- package/clients/file-utils.ts +44 -0
- package/clients/fix-scanners.js +10 -20
- package/clients/fix-scanners.ts +10 -22
- package/clients/format-service.js +172 -0
- package/clients/format-service.ts +254 -0
- package/clients/formatters.js +435 -0
- package/clients/formatters.ts +508 -0
- package/clients/go-client.js +5 -14
- package/clients/go-client.ts +5 -13
- package/clients/installer/index.js +356 -0
- package/clients/installer/index.ts +426 -0
- package/clients/jscpd-client.js +11 -9
- package/clients/jscpd-client.ts +12 -8
- package/clients/knip-client.js +3 -7
- package/clients/knip-client.ts +3 -6
- package/clients/lsp/__tests__/client.test.js +325 -0
- package/clients/lsp/__tests__/client.test.ts +434 -0
- package/clients/lsp/__tests__/config.test.js +166 -0
- package/clients/lsp/__tests__/config.test.ts +209 -0
- package/clients/lsp/__tests__/error-recovery.test.js +213 -0
- package/clients/lsp/__tests__/error-recovery.test.ts +279 -0
- package/clients/lsp/__tests__/integration.test.js +127 -0
- package/clients/lsp/__tests__/integration.test.ts +160 -0
- package/clients/lsp/__tests__/launch.test.js +260 -0
- package/clients/lsp/__tests__/launch.test.ts +329 -0
- package/clients/lsp/__tests__/server.test.js +259 -0
- package/clients/lsp/__tests__/server.test.ts +332 -0
- package/clients/lsp/__tests__/service.test.js +417 -0
- package/clients/lsp/__tests__/service.test.ts +499 -0
- package/clients/lsp/client.js +235 -0
- package/clients/lsp/client.ts +328 -0
- package/clients/lsp/config.js +115 -0
- package/clients/lsp/config.ts +149 -0
- package/clients/lsp/index.js +222 -0
- package/clients/lsp/index.ts +280 -0
- package/clients/lsp/installer/index.js +391 -0
- package/clients/lsp/interactive-install.js +210 -0
- package/clients/lsp/interactive-install.ts +251 -0
- package/clients/lsp/language.js +170 -0
- package/clients/lsp/language.ts +216 -0
- package/clients/lsp/launch.js +174 -0
- package/clients/lsp/launch.ts +240 -0
- package/clients/lsp/lsp/launch.js +116 -0
- package/clients/lsp/lsp/server.js +532 -0
- package/clients/lsp/lsp-index.js +10 -0
- package/clients/lsp/lsp-index.ts +11 -0
- package/clients/lsp/path-utils.js +48 -0
- package/clients/lsp/path-utils.ts +52 -0
- package/clients/lsp/server.js +615 -0
- package/clients/lsp/server.ts +800 -0
- package/clients/lsp/test-py-spawn/requirements.txt +1 -0
- package/clients/lsp/test-py-spawn/test.py +3 -0
- package/clients/lsp/test-py-svc/requirements.txt +1 -0
- package/clients/lsp/test-py-svc/test.py +3 -0
- package/clients/lsp/test-python-project/requirements.txt +1 -0
- package/clients/lsp/test-python-project/test.py +5 -0
- package/clients/metrics-history.js +2 -2
- package/clients/metrics-history.ts +2 -2
- package/clients/production-readiness.js +522 -0
- package/clients/production-readiness.ts +556 -0
- package/clients/project-index.js +255 -0
- package/clients/project-index.ts +383 -0
- package/clients/project-metadata.js +531 -0
- package/clients/project-metadata.ts +624 -0
- package/clients/ruff-client.js +56 -16
- package/clients/ruff-client.ts +72 -15
- package/clients/runner-tracker.js +152 -0
- package/clients/runner-tracker.ts +213 -0
- package/clients/rust-client.js +4 -11
- package/clients/rust-client.ts +5 -11
- package/clients/safe-spawn.js +96 -0
- package/clients/safe-spawn.ts +128 -0
- package/clients/scan-architectural-debt.js +3 -6
- package/clients/scan-architectural-debt.ts +3 -6
- package/clients/scan-utils.js +5 -20
- package/clients/scan-utils.ts +5 -29
- package/clients/secrets-scanner.js +3 -17
- package/clients/secrets-scanner.ts +4 -20
- package/clients/services/__tests__/effect-integration.test.js +86 -0
- package/clients/services/__tests__/effect-integration.test.ts +111 -0
- package/clients/services/effect-integration.js +194 -0
- package/clients/services/effect-integration.ts +268 -0
- package/clients/services/index.js +7 -0
- package/clients/services/index.ts +8 -0
- package/clients/services/runner-service.js +105 -0
- package/clients/services/runner-service.ts +179 -0
- package/clients/sg-runner.js +87 -13
- package/clients/sg-runner.ts +97 -13
- package/clients/state-matrix.js +160 -0
- package/clients/state-matrix.ts +202 -0
- package/clients/subprocess-client.js +10 -9
- package/clients/subprocess-client.ts +10 -8
- package/clients/test-runner-client.js +3 -7
- package/clients/test-runner-client.ts +3 -6
- package/clients/tool-availability.js +4 -10
- package/clients/tool-availability.ts +4 -9
- package/clients/tree-sitter-client.js +564 -0
- package/clients/tree-sitter-client.ts +797 -0
- package/clients/tree-sitter-query-loader.js +355 -0
- package/clients/tree-sitter-query-loader.ts +425 -0
- package/clients/type-coverage-client.js +3 -7
- package/clients/type-coverage-client.ts +3 -6
- package/clients/typescript-client.codefix.test.js +157 -0
- package/clients/typescript-client.codefix.test.ts +186 -0
- package/clients/typescript-client.js +43 -0
- package/clients/typescript-client.ts +98 -0
- package/commands/booboo.js +799 -219
- package/commands/booboo.ts +1004 -225
- package/commands/clients/ast-grep-client.js +250 -0
- package/commands/clients/ast-grep-parser.js +86 -0
- package/commands/clients/ast-grep-rule-manager.js +91 -0
- package/commands/clients/ast-grep-types.js +9 -0
- package/commands/clients/biome-client.js +380 -0
- package/commands/clients/complexity-client.js +667 -0
- package/commands/clients/file-kinds.js +177 -0
- package/commands/clients/file-utils.js +40 -0
- package/commands/clients/jscpd-client.js +169 -0
- package/commands/clients/knip-client.js +211 -0
- package/commands/clients/ruff-client.js +297 -0
- package/commands/clients/safe-spawn.js +88 -0
- package/commands/clients/scan-utils.js +83 -0
- package/commands/clients/sg-runner.js +190 -0
- package/commands/clients/types.js +11 -0
- package/commands/clients/typescript-client.js +505 -0
- package/commands/fix-from-booboo.js +398 -0
- package/commands/fix-from-booboo.ts +485 -0
- package/commands/fix-simplified.js +618 -0
- package/commands/fix-simplified.ts +768 -0
- package/commands/rate.js +10 -14
- package/commands/rate.ts +9 -16
- package/default-architect.yaml +59 -15
- package/index.ts +342 -429
- package/package.json +16 -3
- package/rules/ast-grep-rules/rules/empty-catch.yml +38 -13
- package/rules/ast-grep-rules/rules/no-array-constructor.yml +1 -0
- package/rules/ast-grep-rules/rules/no-debugger.yml +2 -0
- package/rules/python-slop-rules/.sgconfig.yml +4 -0
- package/rules/python-slop-rules/rules/slop-rules.yml +647 -0
- package/rules/tree-sitter-queries/python/bare-except.yml +54 -0
- package/rules/tree-sitter-queries/python/eval-exec.yml +50 -0
- package/rules/tree-sitter-queries/python/is-vs-equals.yml +60 -0
- package/rules/tree-sitter-queries/python/mutable-default-arg.yml +57 -0
- package/rules/tree-sitter-queries/python/unreachable-except.yml +60 -0
- package/rules/tree-sitter-queries/python/wildcard-import.yml +46 -0
- package/rules/tree-sitter-queries/tsx/dangerously-set-inner-html.yml +63 -0
- package/rules/tree-sitter-queries/typescript/await-in-loop.yml +56 -0
- package/rules/tree-sitter-queries/typescript/console-statement.yml +47 -0
- package/rules/tree-sitter-queries/typescript/debugger.yml +47 -0
- package/rules/tree-sitter-queries/typescript/deep-nesting.yml +117 -0
- package/rules/tree-sitter-queries/typescript/deep-promise-chain.yml +73 -0
- package/rules/tree-sitter-queries/typescript/empty-catch.yml +64 -0
- package/rules/tree-sitter-queries/typescript/eval.yml +48 -0
- package/rules/tree-sitter-queries/typescript/hardcoded-secrets.yml +78 -0
- package/rules/tree-sitter-queries/typescript/long-parameter-list.yml +62 -0
- package/rules/tree-sitter-queries/typescript/mixed-async-styles.yml +49 -0
- package/rules/tree-sitter-queries/typescript/nested-ternary.yml +45 -0
- package/rules/ts-slop-rules/.sgconfig.yml +4 -0
- package/rules/ts-slop-rules/rules/in-correct-optional-input-type.yml +10 -0
- package/rules/ts-slop-rules/rules/jwt-no-verify.yml +13 -0
- package/rules/ts-slop-rules/rules/no-architecture-violation.yml +10 -0
- package/rules/ts-slop-rules/rules/no-case-declarations.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dangerously-set-inner-html.yml +10 -0
- package/rules/ts-slop-rules/rules/no-debugger.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-args.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-class-members.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-keys.yml +10 -0
- package/rules/ts-slop-rules/rules/no-eval.yml +13 -0
- package/rules/ts-slop-rules/rules/no-hardcoded-secrets.yml +12 -0
- package/rules/ts-slop-rules/rules/no-implied-eval.yml +12 -0
- package/rules/ts-slop-rules/rules/no-inner-html.yml +13 -0
- package/rules/ts-slop-rules/rules/no-javascript-url.yml +10 -0
- package/rules/ts-slop-rules/rules/no-mutable-default.yml +10 -0
- package/rules/ts-slop-rules/rules/no-nested-links.yml +12 -0
- package/rules/ts-slop-rules/rules/no-new-symbol.yml +10 -0
- package/rules/ts-slop-rules/rules/no-new-wrappers.yml +13 -0
- package/rules/ts-slop-rules/rules/no-open-redirect.yml +16 -0
- package/rules/ts-slop-rules/rules/slop-rules.yml +455 -0
- package/rules/ts-slop-rules/rules/weak-rsa-key.yml +12 -0
- package/skills/ast-grep/SKILL.md +182 -0
- package/clients/dispatch/runners/secrets.js +0 -109
- package/commands/fix.js +0 -244
- package/commands/fix.ts +0 -373
- package/rules/ast-grep-rules/rules/no-lonely-if.yml +0 -13
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Matrix Builder
|
|
3
|
+
*
|
|
4
|
+
* Implements Amain's 57×72 state transfer matrix construction.
|
|
5
|
+
* Counts parent→child transitions in the TypeScript AST.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as ts from "typescript";
|
|
9
|
+
import { getStateIndex, NUM_STATES, NUM_SYNTAX } from "./amain-types.js";
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Matrix Construction
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Build a 57×72 state transfer matrix from TypeScript source code.
|
|
17
|
+
*
|
|
18
|
+
* matrix[i][j] = count of transitions from syntax state i to state j
|
|
19
|
+
*
|
|
20
|
+
* @param sourceCode TypeScript source code
|
|
21
|
+
* @returns 57×72 matrix of transition counts
|
|
22
|
+
*/
|
|
23
|
+
export function buildStateMatrix(sourceCode: string): number[][] {
|
|
24
|
+
const sourceFile = ts.createSourceFile(
|
|
25
|
+
"temp.ts",
|
|
26
|
+
sourceCode,
|
|
27
|
+
ts.ScriptTarget.Latest,
|
|
28
|
+
true,
|
|
29
|
+
ts.ScriptKind.TS,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Initialize 57×72 matrix with zeros
|
|
33
|
+
const matrix: number[][] = Array(NUM_SYNTAX)
|
|
34
|
+
.fill(0)
|
|
35
|
+
.map(() => Array(NUM_STATES).fill(0));
|
|
36
|
+
|
|
37
|
+
// Walk AST and count transitions
|
|
38
|
+
function visitNode(node: ts.Node, parentKind?: number) {
|
|
39
|
+
const nodeState = getStateIndex(node);
|
|
40
|
+
|
|
41
|
+
if (parentKind !== undefined) {
|
|
42
|
+
const parentState = getStateIndex({ kind: parentKind } as ts.Node);
|
|
43
|
+
// Only count transitions from syntax states (first 57)
|
|
44
|
+
if (parentState < NUM_SYNTAX) {
|
|
45
|
+
matrix[parentState][nodeState]++;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Continue to children
|
|
50
|
+
ts.forEachChild(node, (child) => visitNode(child, node.kind));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
visitNode(sourceFile);
|
|
54
|
+
return matrix;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Build matrix from a source file node (for incremental updates)
|
|
59
|
+
*/
|
|
60
|
+
export function buildStateMatrixFromFile(
|
|
61
|
+
sourceFile: ts.SourceFile,
|
|
62
|
+
): number[][] {
|
|
63
|
+
// Initialize 57×72 matrix with zeros
|
|
64
|
+
const matrix: number[][] = Array(NUM_SYNTAX)
|
|
65
|
+
.fill(0)
|
|
66
|
+
.map(() => Array(NUM_STATES).fill(0));
|
|
67
|
+
|
|
68
|
+
// Walk AST and count transitions
|
|
69
|
+
function visitNode(node: ts.Node, parentKind?: number) {
|
|
70
|
+
const nodeState = getStateIndex(node);
|
|
71
|
+
|
|
72
|
+
if (parentKind !== undefined) {
|
|
73
|
+
const parentState = getStateIndex({ kind: parentKind } as ts.Node);
|
|
74
|
+
// Only count transitions from syntax states (first 57)
|
|
75
|
+
if (parentState < NUM_SYNTAX) {
|
|
76
|
+
matrix[parentState][nodeState]++;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Continue to children
|
|
81
|
+
ts.forEachChild(node, (child) => visitNode(child, node.kind));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
visitNode(sourceFile);
|
|
85
|
+
return matrix;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ============================================================================
|
|
89
|
+
// Probability Normalization
|
|
90
|
+
// ============================================================================
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Convert count matrix to probability matrix.
|
|
94
|
+
* Each row sums to 1 (Markov chain property).
|
|
95
|
+
*
|
|
96
|
+
* @param matrix 57×72 count matrix
|
|
97
|
+
* @returns 57×72 probability matrix
|
|
98
|
+
*/
|
|
99
|
+
export function toProbabilityMatrix(matrix: number[][]): number[][] {
|
|
100
|
+
return matrix.map((row) => {
|
|
101
|
+
const sum = row.reduce((a, b) => a + b, 0);
|
|
102
|
+
if (sum === 0) return row.map(() => 0);
|
|
103
|
+
return row.map((val) => val / sum);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ============================================================================
|
|
108
|
+
// Similarity Calculation
|
|
109
|
+
// ============================================================================
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Calculate cosine similarity between two state matrices.
|
|
113
|
+
* Returns 0-1 similarity score (1 = identical).
|
|
114
|
+
*
|
|
115
|
+
* @param matrix1 57×72 count matrix
|
|
116
|
+
* @param matrix2 57×72 count matrix
|
|
117
|
+
* @returns similarity score 0-1
|
|
118
|
+
*/
|
|
119
|
+
export function calculateSimilarity(
|
|
120
|
+
matrix1: number[][],
|
|
121
|
+
matrix2: number[][],
|
|
122
|
+
): number {
|
|
123
|
+
const prob1 = toProbabilityMatrix(matrix1);
|
|
124
|
+
const prob2 = toProbabilityMatrix(matrix2);
|
|
125
|
+
|
|
126
|
+
const similarities: number[] = [];
|
|
127
|
+
|
|
128
|
+
for (let i = 0; i < NUM_SYNTAX; i++) {
|
|
129
|
+
const row1 = prob1[i];
|
|
130
|
+
const row2 = prob2[i];
|
|
131
|
+
|
|
132
|
+
// Skip if both rows are empty
|
|
133
|
+
const hasData1 = row1.some((v) => v > 0);
|
|
134
|
+
const hasData2 = row2.some((v) => v > 0);
|
|
135
|
+
|
|
136
|
+
if (hasData1 || hasData2) {
|
|
137
|
+
// Calculate cosine similarity for this state
|
|
138
|
+
let dotProduct = 0;
|
|
139
|
+
let norm1 = 0;
|
|
140
|
+
let norm2 = 0;
|
|
141
|
+
|
|
142
|
+
for (let j = 0; j < NUM_STATES; j++) {
|
|
143
|
+
dotProduct += row1[j] * row2[j];
|
|
144
|
+
norm1 += row1[j] * row1[j];
|
|
145
|
+
norm2 += row2[j] * row2[j];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (norm1 > 0 && norm2 > 0) {
|
|
149
|
+
similarities.push(dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2)));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Return average similarity across all states
|
|
155
|
+
if (similarities.length === 0) return 0;
|
|
156
|
+
return similarities.reduce((a, b) => a + b, 0) / similarities.length;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Calculate similarity from source code directly (convenience method)
|
|
161
|
+
*/
|
|
162
|
+
export function calculateSimilarityFromCode(
|
|
163
|
+
code1: string,
|
|
164
|
+
code2: string,
|
|
165
|
+
): number {
|
|
166
|
+
const matrix1 = buildStateMatrix(code1);
|
|
167
|
+
const matrix2 = buildStateMatrix(code2);
|
|
168
|
+
return calculateSimilarity(matrix1, matrix2);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ============================================================================
|
|
172
|
+
// Matrix Statistics (for guardrails)
|
|
173
|
+
// ============================================================================
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Count total non-zero transitions in matrix (proxy for function complexity)
|
|
177
|
+
*/
|
|
178
|
+
export function countTransitions(matrix: number[][]): number {
|
|
179
|
+
return matrix.flat().filter((v) => v > 0).length;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Check if function meets complexity threshold (>20 transitions)
|
|
184
|
+
*/
|
|
185
|
+
export function isComplexEnough(matrix: number[][]): boolean {
|
|
186
|
+
return countTransitions(matrix) >= 20;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Serialize matrix for storage (sparse format to save space)
|
|
191
|
+
*/
|
|
192
|
+
export function serializeMatrix(matrix: number[][]): number[][] {
|
|
193
|
+
// Return full matrix for now - can optimize to sparse later if needed
|
|
194
|
+
return matrix;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Deserialize matrix from storage
|
|
199
|
+
*/
|
|
200
|
+
export function deserializeMatrix(data: number[][]): number[][] {
|
|
201
|
+
return data;
|
|
202
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
1
|
import * as path from "node:path";
|
|
2
|
+
import { safeSpawn } from "./safe-spawn.js";
|
|
3
3
|
export class SubprocessClient {
|
|
4
4
|
constructor(verbose = false) {
|
|
5
5
|
this.available = null;
|
|
@@ -13,10 +13,8 @@ export class SubprocessClient {
|
|
|
13
13
|
return this.available;
|
|
14
14
|
const cmd = this.getCheckCommand();
|
|
15
15
|
try {
|
|
16
|
-
const result =
|
|
17
|
-
encoding: "utf-8",
|
|
16
|
+
const result = safeSpawn(cmd[0], cmd.slice(1), {
|
|
18
17
|
timeout: 10000,
|
|
19
|
-
shell: true,
|
|
20
18
|
});
|
|
21
19
|
this.available = !result.error && result.status === 0;
|
|
22
20
|
if (this.available) {
|
|
@@ -39,17 +37,20 @@ export class SubprocessClient {
|
|
|
39
37
|
runCommand(cmd, options = {}) {
|
|
40
38
|
const { cwd, timeout = 15000, input } = options;
|
|
41
39
|
try {
|
|
42
|
-
const result =
|
|
43
|
-
encoding: "utf-8",
|
|
40
|
+
const result = safeSpawn(cmd[0], cmd.slice(1), {
|
|
44
41
|
timeout,
|
|
45
42
|
cwd,
|
|
46
|
-
shell: true,
|
|
47
|
-
input,
|
|
48
43
|
});
|
|
49
44
|
if (result.error) {
|
|
50
45
|
this.log(`Command error: ${result.error.message}`);
|
|
51
46
|
}
|
|
52
|
-
return
|
|
47
|
+
// Return in a shape compatible with spawnSync return type
|
|
48
|
+
return {
|
|
49
|
+
status: result.status,
|
|
50
|
+
stdout: result.stdout,
|
|
51
|
+
stderr: result.stderr,
|
|
52
|
+
error: result.error,
|
|
53
|
+
};
|
|
53
54
|
}
|
|
54
55
|
catch (err) {
|
|
55
56
|
this.log(`Command failed: ${err.message}`);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
import { safeSpawn } from "./safe-spawn.js";
|
|
3
4
|
|
|
4
5
|
export interface Diagnostic {
|
|
5
6
|
line: number;
|
|
@@ -35,10 +36,8 @@ export abstract class SubprocessClient<T extends Diagnostic> {
|
|
|
35
36
|
|
|
36
37
|
const cmd = this.getCheckCommand();
|
|
37
38
|
try {
|
|
38
|
-
const result =
|
|
39
|
-
encoding: "utf-8",
|
|
39
|
+
const result = safeSpawn(cmd[0], cmd.slice(1), {
|
|
40
40
|
timeout: 10000,
|
|
41
|
-
shell: true,
|
|
42
41
|
});
|
|
43
42
|
|
|
44
43
|
this.available = !result.error && result.status === 0;
|
|
@@ -73,19 +72,22 @@ export abstract class SubprocessClient<T extends Diagnostic> {
|
|
|
73
72
|
const { cwd, timeout = 15000, input } = options;
|
|
74
73
|
|
|
75
74
|
try {
|
|
76
|
-
const result =
|
|
77
|
-
encoding: "utf-8",
|
|
75
|
+
const result = safeSpawn(cmd[0], cmd.slice(1), {
|
|
78
76
|
timeout,
|
|
79
77
|
cwd,
|
|
80
|
-
shell: true,
|
|
81
|
-
input,
|
|
82
78
|
});
|
|
83
79
|
|
|
84
80
|
if (result.error) {
|
|
85
81
|
this.log(`Command error: ${result.error.message}`);
|
|
86
82
|
}
|
|
87
83
|
|
|
88
|
-
return
|
|
84
|
+
// Return in a shape compatible with spawnSync return type
|
|
85
|
+
return {
|
|
86
|
+
status: result.status,
|
|
87
|
+
stdout: result.stdout,
|
|
88
|
+
stderr: result.stderr,
|
|
89
|
+
error: result.error,
|
|
90
|
+
} as unknown as ReturnType<typeof spawnSync>;
|
|
89
91
|
} catch (err: any) {
|
|
90
92
|
this.log(`Command failed: ${err.message}`);
|
|
91
93
|
return {
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
* Design: File-level targeted testing — only runs tests for the
|
|
10
10
|
* specific file being edited, not the entire suite.
|
|
11
11
|
*/
|
|
12
|
-
import { spawnSync } from "node:child_process";
|
|
13
12
|
import * as fs from "node:fs";
|
|
14
13
|
import * as path from "node:path";
|
|
14
|
+
import { safeSpawn } from "./safe-spawn.js";
|
|
15
15
|
// --- Test File Patterns ---
|
|
16
16
|
const _TEST_FILE_PATTERNS = [
|
|
17
17
|
{
|
|
@@ -250,10 +250,8 @@ export class TestRunnerClient {
|
|
|
250
250
|
// Priority 5: Check if pytest is available globally (for Python)
|
|
251
251
|
try {
|
|
252
252
|
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
253
|
-
const result =
|
|
254
|
-
encoding: "utf-8",
|
|
253
|
+
const result = safeSpawn(whichCmd, ["pytest"], {
|
|
255
254
|
timeout: 2000,
|
|
256
|
-
shell: true,
|
|
257
255
|
});
|
|
258
256
|
if (result.status === 0) {
|
|
259
257
|
this.log("Detected pytest globally");
|
|
@@ -336,11 +334,9 @@ export class TestRunnerClient {
|
|
|
336
334
|
try {
|
|
337
335
|
const args = config.args(absoluteTestFile, cwd);
|
|
338
336
|
this.log(`Running: ${config.command} ${args.join(" ")}`);
|
|
339
|
-
const result =
|
|
340
|
-
encoding: "utf-8",
|
|
337
|
+
const result = safeSpawn(config.command, args, {
|
|
341
338
|
cwd,
|
|
342
339
|
timeout: 60000, // 60s timeout
|
|
343
|
-
shell: true,
|
|
344
340
|
});
|
|
345
341
|
const stdout = result.stdout || "";
|
|
346
342
|
const stderr = result.stderr || "";
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { spawnSync } from "node:child_process";
|
|
14
14
|
import * as fs from "node:fs";
|
|
15
15
|
import * as path from "node:path";
|
|
16
|
+
import { safeSpawn } from "./safe-spawn.js";
|
|
16
17
|
|
|
17
18
|
// --- Types ---
|
|
18
19
|
|
|
@@ -303,10 +304,8 @@ export class TestRunnerClient {
|
|
|
303
304
|
// Priority 5: Check if pytest is available globally (for Python)
|
|
304
305
|
try {
|
|
305
306
|
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
306
|
-
const result =
|
|
307
|
-
encoding: "utf-8",
|
|
307
|
+
const result = safeSpawn(whichCmd, ["pytest"], {
|
|
308
308
|
timeout: 2000,
|
|
309
|
-
shell: true,
|
|
310
309
|
});
|
|
311
310
|
if (result.status === 0) {
|
|
312
311
|
this.log("Detected pytest globally");
|
|
@@ -413,11 +412,9 @@ export class TestRunnerClient {
|
|
|
413
412
|
const args = config.args(absoluteTestFile, cwd);
|
|
414
413
|
this.log(`Running: ${config.command} ${args.join(" ")}`);
|
|
415
414
|
|
|
416
|
-
const result =
|
|
417
|
-
encoding: "utf-8",
|
|
415
|
+
const result = safeSpawn(config.command, args, {
|
|
418
416
|
cwd,
|
|
419
417
|
timeout: 60000, // 60s timeout
|
|
420
|
-
shell: true,
|
|
421
418
|
});
|
|
422
419
|
|
|
423
420
|
const stdout = result.stdout || "";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Provides cached tool availability checks to avoid repeated spawnSync calls.
|
|
5
5
|
* Tools like biome, ruff, ast-grep are checked once per session.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { safeSpawn } from "./safe-spawn.js";
|
|
8
8
|
// --- Tool Registry ---
|
|
9
9
|
export const TOOL_REGISTRY = [
|
|
10
10
|
{
|
|
@@ -91,10 +91,8 @@ export function isToolAvailable(toolName) {
|
|
|
91
91
|
const tool = TOOL_REGISTRY.find((t) => t.name === toolName);
|
|
92
92
|
if (!tool) {
|
|
93
93
|
// Unknown tool - try direct command check
|
|
94
|
-
const result =
|
|
95
|
-
encoding: "utf-8",
|
|
94
|
+
const result = safeSpawn(toolName, ["--version"], {
|
|
96
95
|
timeout: 5000,
|
|
97
|
-
shell: true,
|
|
98
96
|
});
|
|
99
97
|
const available = !result.error && result.status === 0;
|
|
100
98
|
TOOL_CACHE.set(toolName, {
|
|
@@ -108,10 +106,8 @@ export function isToolAvailable(toolName) {
|
|
|
108
106
|
}
|
|
109
107
|
// Check using tool's version command
|
|
110
108
|
if (tool.versionCommand) {
|
|
111
|
-
const result =
|
|
112
|
-
encoding: "utf-8",
|
|
109
|
+
const result = safeSpawn(tool.command, tool.versionCommand, {
|
|
113
110
|
timeout: 10000,
|
|
114
|
-
shell: true,
|
|
115
111
|
});
|
|
116
112
|
const available = !result.error && result.status === 0;
|
|
117
113
|
const output = result.stdout + result.stderr;
|
|
@@ -138,10 +134,8 @@ export function getToolVersion(toolName) {
|
|
|
138
134
|
// Try to get version even if not cached
|
|
139
135
|
const tool = TOOL_REGISTRY.find((t) => t.name === toolName);
|
|
140
136
|
if (tool?.versionCommand) {
|
|
141
|
-
const result =
|
|
142
|
-
encoding: "utf-8",
|
|
137
|
+
const result = safeSpawn(tool.command, tool.versionCommand, {
|
|
143
138
|
timeout: 10000,
|
|
144
|
-
shell: true,
|
|
145
139
|
});
|
|
146
140
|
if (!result.error && result.status === 0) {
|
|
147
141
|
const output = result.stdout + result.stderr;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { spawnSync } from "node:child_process";
|
|
9
|
+
import { safeSpawn } from "./safe-spawn.js";
|
|
9
10
|
|
|
10
11
|
// --- Types ---
|
|
11
12
|
|
|
@@ -116,10 +117,8 @@ export function isToolAvailable(toolName: string): boolean {
|
|
|
116
117
|
const tool = TOOL_REGISTRY.find((t) => t.name === toolName);
|
|
117
118
|
if (!tool) {
|
|
118
119
|
// Unknown tool - try direct command check
|
|
119
|
-
const result =
|
|
120
|
-
encoding: "utf-8",
|
|
120
|
+
const result = safeSpawn(toolName, ["--version"], {
|
|
121
121
|
timeout: 5000,
|
|
122
|
-
shell: true,
|
|
123
122
|
});
|
|
124
123
|
const available = !result.error && result.status === 0;
|
|
125
124
|
TOOL_CACHE.set(toolName, {
|
|
@@ -134,10 +133,8 @@ export function isToolAvailable(toolName: string): boolean {
|
|
|
134
133
|
|
|
135
134
|
// Check using tool's version command
|
|
136
135
|
if (tool.versionCommand) {
|
|
137
|
-
const result =
|
|
138
|
-
encoding: "utf-8",
|
|
136
|
+
const result = safeSpawn(tool.command, tool.versionCommand, {
|
|
139
137
|
timeout: 10000,
|
|
140
|
-
shell: true,
|
|
141
138
|
});
|
|
142
139
|
const available = !result.error && result.status === 0;
|
|
143
140
|
const output = result.stdout + result.stderr;
|
|
@@ -169,10 +166,8 @@ export function getToolVersion(toolName: string): string | undefined {
|
|
|
169
166
|
// Try to get version even if not cached
|
|
170
167
|
const tool = TOOL_REGISTRY.find((t) => t.name === toolName);
|
|
171
168
|
if (tool?.versionCommand) {
|
|
172
|
-
const result =
|
|
173
|
-
encoding: "utf-8",
|
|
169
|
+
const result = safeSpawn(tool.command, tool.versionCommand, {
|
|
174
170
|
timeout: 10000,
|
|
175
|
-
shell: true,
|
|
176
171
|
});
|
|
177
172
|
if (!result.error && result.status === 0) {
|
|
178
173
|
const output = result.stdout + result.stderr;
|