@rigour-labs/core 6.8.0 → 6.8.1-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/inference/cloud-provider.js +12 -2
- package/package.json +11 -8
- package/dist/brief/briefing.test.d.ts +0 -1
- package/dist/brief/briefing.test.js +0 -107
- package/dist/context/automatic-index-cache.test.d.ts +0 -1
- package/dist/context/automatic-index-cache.test.js +0 -30
- package/dist/context/automatic-index.test.d.ts +0 -1
- package/dist/context/automatic-index.test.js +0 -45
- package/dist/context/cache-engine.test.d.ts +0 -1
- package/dist/context/cache-engine.test.js +0 -99
- package/dist/context/dependency-graph.test.d.ts +0 -1
- package/dist/context/dependency-graph.test.js +0 -13
- package/dist/context/index-status.test.d.ts +0 -1
- package/dist/context/index-status.test.js +0 -26
- package/dist/context.test.d.ts +0 -1
- package/dist/context.test.js +0 -228
- package/dist/deep/agent-review.test.d.ts +0 -1
- package/dist/deep/agent-review.test.js +0 -53
- package/dist/deep/code-context.test.d.ts +0 -1
- package/dist/deep/code-context.test.js +0 -48
- package/dist/deep/code-pass.test.d.ts +0 -1
- package/dist/deep/code-pass.test.js +0 -112
- package/dist/deep/code-review-prompt.test.d.ts +0 -1
- package/dist/deep/code-review-prompt.test.js +0 -20
- package/dist/deep/code-verifier.test.d.ts +0 -1
- package/dist/deep/code-verifier.test.js +0 -54
- package/dist/deep/diff-tests/calls.test.d.ts +0 -1
- package/dist/deep/diff-tests/calls.test.js +0 -33
- package/dist/deep/diff-tests/run.test.d.ts +0 -1
- package/dist/deep/diff-tests/run.test.js +0 -58
- package/dist/deep/fact-extractor.test.d.ts +0 -1
- package/dist/deep/fact-extractor.test.js +0 -581
- package/dist/deep/parse-findings.test.d.ts +0 -1
- package/dist/deep/parse-findings.test.js +0 -25
- package/dist/deep/pr-review.test.d.ts +0 -1
- package/dist/deep/pr-review.test.js +0 -80
- package/dist/deep/prompts.test.d.ts +0 -1
- package/dist/deep/prompts.test.js +0 -235
- package/dist/deep/reference-pack.test.d.ts +0 -1
- package/dist/deep/reference-pack.test.js +0 -46
- package/dist/deep/related-changes.test.d.ts +0 -1
- package/dist/deep/related-changes.test.js +0 -33
- package/dist/deep/review-context-export.test.d.ts +0 -1
- package/dist/deep/review-context-export.test.js +0 -32
- package/dist/deep/review-tools.test.d.ts +0 -1
- package/dist/deep/review-tools.test.js +0 -39
- package/dist/deep/risk.test.d.ts +0 -1
- package/dist/deep/risk.test.js +0 -101
- package/dist/deep/verifier.test.d.ts +0 -1
- package/dist/deep/verifier.test.js +0 -635
- package/dist/discovery.test.d.ts +0 -1
- package/dist/discovery.test.js +0 -93
- package/dist/environment.test.d.ts +0 -1
- package/dist/environment.test.js +0 -94
- package/dist/firewall/firewall.test.d.ts +0 -1
- package/dist/firewall/firewall.test.js +0 -117
- package/dist/firewall/trust-boundaries.test.d.ts +0 -1
- package/dist/firewall/trust-boundaries.test.js +0 -64
- package/dist/firewall/trusted-control.test.d.ts +0 -1
- package/dist/firewall/trusted-control.test.js +0 -188
- package/dist/gates/agent-team.test.d.ts +0 -1
- package/dist/gates/agent-team.test.js +0 -113
- package/dist/gates/ast.test.d.ts +0 -1
- package/dist/gates/ast.test.js +0 -112
- package/dist/gates/checkpoint.test.d.ts +0 -1
- package/dist/gates/checkpoint.test.js +0 -105
- package/dist/gates/content.test.d.ts +0 -1
- package/dist/gates/content.test.js +0 -73
- package/dist/gates/coverage.test.d.ts +0 -1
- package/dist/gates/coverage.test.js +0 -53
- package/dist/gates/dedupe-failures.test.d.ts +0 -1
- package/dist/gates/dedupe-failures.test.js +0 -12
- package/dist/gates/deep-analysis.test.d.ts +0 -1
- package/dist/gates/deep-analysis.test.js +0 -86
- package/dist/gates/deep-intent.test.d.ts +0 -1
- package/dist/gates/deep-intent.test.js +0 -51
- package/dist/gates/deep-timeout.test.d.ts +0 -1
- package/dist/gates/deep-timeout.test.js +0 -10
- package/dist/gates/deprecated-apis.test.d.ts +0 -1
- package/dist/gates/deprecated-apis.test.js +0 -318
- package/dist/gates/deprecated-dependencies.test.d.ts +0 -1
- package/dist/gates/deprecated-dependencies.test.js +0 -55
- package/dist/gates/frontend-secret-exposure.test.d.ts +0 -1
- package/dist/gates/frontend-secret-exposure.test.js +0 -148
- package/dist/gates/hallucinated-imports/framework-modules-nuxt.test.d.ts +0 -1
- package/dist/gates/hallucinated-imports/framework-modules-nuxt.test.js +0 -27
- package/dist/gates/hallucinated-imports/js-resolver-types.test.d.ts +0 -1
- package/dist/gates/hallucinated-imports/js-resolver-types.test.js +0 -14
- package/dist/gates/hallucinated-imports-sveltekit.test.d.ts +0 -1
- package/dist/gates/hallucinated-imports-sveltekit.test.js +0 -132
- package/dist/gates/hallucinated-imports.test.d.ts +0 -1
- package/dist/gates/hallucinated-imports.test.js +0 -1206
- package/dist/gates/js-style-context.test.d.ts +0 -1
- package/dist/gates/js-style-context.test.js +0 -35
- package/dist/gates/logic-drift.test.d.ts +0 -1
- package/dist/gates/logic-drift.test.js +0 -52
- package/dist/gates/phantom-apis.test.d.ts +0 -1
- package/dist/gates/phantom-apis.test.js +0 -396
- package/dist/gates/promise-safety.test.d.ts +0 -1
- package/dist/gates/promise-safety.test.js +0 -34
- package/dist/gates/runner.test.d.ts +0 -1
- package/dist/gates/runner.test.js +0 -77
- package/dist/gates/scoped-gates.test.d.ts +0 -1
- package/dist/gates/scoped-gates.test.js +0 -52
- package/dist/gates/security-patterns-owasp.test.d.ts +0 -1
- package/dist/gates/security-patterns-owasp.test.js +0 -186
- package/dist/gates/security-patterns.test.d.ts +0 -1
- package/dist/gates/security-patterns.test.js +0 -194
- package/dist/gates/semantic-bugs.test.d.ts +0 -1
- package/dist/gates/semantic-bugs.test.js +0 -76
- package/dist/gates/side-effect-analysis.test.d.ts +0 -1
- package/dist/gates/side-effect-analysis.test.js +0 -162
- package/dist/gates/style-drift.test.d.ts +0 -1
- package/dist/gates/style-drift.test.js +0 -26
- package/dist/gates/test-quality.test.d.ts +0 -1
- package/dist/gates/test-quality.test.js +0 -325
- package/dist/gates/trusted-reviews.test.d.ts +0 -1
- package/dist/gates/trusted-reviews.test.js +0 -16
- package/dist/gates/unindexed-reads/queries.test.d.ts +0 -1
- package/dist/gates/unindexed-reads/queries.test.js +0 -54
- package/dist/gates/unindexed-reads/schema.test.d.ts +0 -1
- package/dist/gates/unindexed-reads/schema.test.js +0 -81
- package/dist/gates/unindexed-reads/unindexed-reads.test.d.ts +0 -1
- package/dist/gates/unindexed-reads/unindexed-reads.test.js +0 -90
- package/dist/hooks/checker.test.d.ts +0 -1
- package/dist/hooks/checker.test.js +0 -159
- package/dist/hooks/dlp-confidence.test.d.ts +0 -1
- package/dist/hooks/dlp-confidence.test.js +0 -51
- package/dist/hooks/dlp-feedback.test.d.ts +0 -1
- package/dist/hooks/dlp-feedback.test.js +0 -131
- package/dist/hooks/input-validator.test.d.ts +0 -1
- package/dist/hooks/input-validator.test.js +0 -329
- package/dist/hooks/templates.test.d.ts +0 -1
- package/dist/hooks/templates.test.js +0 -27
- package/dist/inference/brain-placeholder.test.d.ts +0 -1
- package/dist/inference/brain-placeholder.test.js +0 -28
- package/dist/inference/cloud-provider.test.d.ts +0 -1
- package/dist/inference/cloud-provider.test.js +0 -139
- package/dist/inference/executable.test.d.ts +0 -1
- package/dist/inference/executable.test.js +0 -41
- package/dist/inference/http-download.test.d.ts +0 -1
- package/dist/inference/http-download.test.js +0 -109
- package/dist/inference/llama-engine-checksum.test.d.ts +0 -1
- package/dist/inference/llama-engine-checksum.test.js +0 -27
- package/dist/inference/llama-engine.test.d.ts +0 -1
- package/dist/inference/llama-engine.test.js +0 -51
- package/dist/inference/llama-process.test.d.ts +0 -1
- package/dist/inference/llama-process.test.js +0 -61
- package/dist/inference/local-model.test.d.ts +0 -1
- package/dist/inference/local-model.test.js +0 -23
- package/dist/inference/model-download.test.d.ts +0 -1
- package/dist/inference/model-download.test.js +0 -125
- package/dist/inference/model-manager.test.d.ts +0 -1
- package/dist/inference/model-manager.test.js +0 -24
- package/dist/inference/types.test.d.ts +0 -1
- package/dist/inference/types.test.js +0 -19
- package/dist/memory/recall.test.d.ts +0 -1
- package/dist/memory/recall.test.js +0 -36
- package/dist/pattern-index/indexer.test.d.ts +0 -6
- package/dist/pattern-index/indexer.test.js +0 -197
- package/dist/pattern-index/matcher.test.d.ts +0 -6
- package/dist/pattern-index/matcher.test.js +0 -238
- package/dist/pattern-index/pattern-reuse.test.d.ts +0 -1
- package/dist/pattern-index/pattern-reuse.test.js +0 -76
- package/dist/pattern-index/semantic-runtime.test.d.ts +0 -1
- package/dist/pattern-index/semantic-runtime.test.js +0 -31
- package/dist/pattern-index/staleness.test.d.ts +0 -6
- package/dist/pattern-index/staleness.test.js +0 -211
- package/dist/review/agent-fixes.test.d.ts +0 -1
- package/dist/review/agent-fixes.test.js +0 -32
- package/dist/review/backtest-init.test.d.ts +0 -1
- package/dist/review/backtest-init.test.js +0 -136
- package/dist/review/backtest-judges.test.d.ts +0 -1
- package/dist/review/backtest-judges.test.js +0 -32
- package/dist/review/backtest-last.test.d.ts +0 -1
- package/dist/review/backtest-last.test.js +0 -109
- package/dist/review/backtest.test.d.ts +0 -1
- package/dist/review/backtest.test.js +0 -183
- package/dist/review/baseline.test.d.ts +0 -1
- package/dist/review/baseline.test.js +0 -22
- package/dist/review/branch-checks.test.d.ts +0 -1
- package/dist/review/branch-checks.test.js +0 -48
- package/dist/review/check-outcomes.test.d.ts +0 -1
- package/dist/review/check-outcomes.test.js +0 -56
- package/dist/review/code-patterns.test.d.ts +0 -1
- package/dist/review/code-patterns.test.js +0 -142
- package/dist/review/dead-code.test.d.ts +0 -1
- package/dist/review/dead-code.test.js +0 -154
- package/dist/review/deep-runs.test.d.ts +0 -1
- package/dist/review/deep-runs.test.js +0 -23
- package/dist/review/effectiveness.test.d.ts +0 -1
- package/dist/review/effectiveness.test.js +0 -42
- package/dist/review/fix-scope.test.d.ts +0 -1
- package/dist/review/fix-scope.test.js +0 -104
- package/dist/review/generated-files.test.d.ts +0 -1
- package/dist/review/generated-files.test.js +0 -25
- package/dist/review/migration-order.test.d.ts +0 -1
- package/dist/review/migration-order.test.js +0 -62
- package/dist/review/quiet.test.d.ts +0 -1
- package/dist/review/quiet.test.js +0 -38
- package/dist/review/receipt.test.d.ts +0 -1
- package/dist/review/receipt.test.js +0 -60
- package/dist/review/review-task.test.d.ts +0 -1
- package/dist/review/review-task.test.js +0 -89
- package/dist/review/review.test.d.ts +0 -1
- package/dist/review/review.test.js +0 -203
- package/dist/review/reviewer/adapters.test.d.ts +0 -1
- package/dist/review/reviewer/adapters.test.js +0 -100
- package/dist/review/reviewer/api-judge.test.d.ts +0 -1
- package/dist/review/reviewer/api-judge.test.js +0 -108
- package/dist/review/reviewer/background.test.d.ts +0 -1
- package/dist/review/reviewer/background.test.js +0 -118
- package/dist/review/reviewer/context.test.d.ts +0 -1
- package/dist/review/reviewer/context.test.js +0 -45
- package/dist/review/reviewer/exec.test.d.ts +0 -1
- package/dist/review/reviewer/exec.test.js +0 -59
- package/dist/review/reviewer/inputs.test.d.ts +0 -1
- package/dist/review/reviewer/inputs.test.js +0 -52
- package/dist/review/reviewer/panel.test.d.ts +0 -1
- package/dist/review/reviewer/panel.test.js +0 -110
- package/dist/review/reviewer/record.test.d.ts +0 -1
- package/dist/review/reviewer/record.test.js +0 -40
- package/dist/review/reviewer/rule-writer.test.d.ts +0 -1
- package/dist/review/reviewer/rule-writer.test.js +0 -52
- package/dist/review/reviewer/settings.test.d.ts +0 -1
- package/dist/review/reviewer/settings.test.js +0 -57
- package/dist/review/reviewer/usage.test.d.ts +0 -1
- package/dist/review/reviewer/usage.test.js +0 -14
- package/dist/review/reviewer.test.d.ts +0 -1
- package/dist/review/reviewer.test.js +0 -792
- package/dist/review/stories.test.d.ts +0 -1
- package/dist/review/stories.test.js +0 -58
- package/dist/review/toolchain.test.d.ts +0 -1
- package/dist/review/toolchain.test.js +0 -108
- package/dist/review/typed/redundancy.test.d.ts +0 -1
- package/dist/review/typed/redundancy.test.js +0 -315
- package/dist/review/typed/schema-nullability.test.d.ts +0 -1
- package/dist/review/typed/schema-nullability.test.js +0 -63
- package/dist/review-learning/human-edits.test.d.ts +0 -1
- package/dist/review-learning/human-edits.test.js +0 -47
- package/dist/review-learning/repo-rules.test.d.ts +0 -1
- package/dist/review-learning/repo-rules.test.js +0 -93
- package/dist/review-learning/review-learning.test.d.ts +0 -1
- package/dist/review-learning/review-learning.test.js +0 -249
- package/dist/safety.test.d.ts +0 -1
- package/dist/safety.test.js +0 -42
- package/dist/semantic/benchmark.test.d.ts +0 -1
- package/dist/semantic/benchmark.test.js +0 -22
- package/dist/semantic/intent/intent.test.d.ts +0 -1
- package/dist/semantic/intent/intent.test.js +0 -46
- package/dist/semantic/learn/learn.test.d.ts +0 -1
- package/dist/semantic/learn/learn.test.js +0 -67
- package/dist/semantic/origins.test.d.ts +0 -1
- package/dist/semantic/origins.test.js +0 -77
- package/dist/semantic/project-facts.test.d.ts +0 -1
- package/dist/semantic/project-facts.test.js +0 -45
- package/dist/semantic/sites/call-sites.test.d.ts +0 -1
- package/dist/semantic/sites/call-sites.test.js +0 -46
- package/dist/services/adaptive-thresholds.test.d.ts +0 -1
- package/dist/services/adaptive-thresholds.test.js +0 -53
- package/dist/services/agent-history.test.d.ts +0 -1
- package/dist/services/agent-history.test.js +0 -69
- package/dist/services/context-scope-summary.test.d.ts +0 -1
- package/dist/services/context-scope-summary.test.js +0 -17
- package/dist/services/context-telemetry-service.test.d.ts +0 -1
- package/dist/services/context-telemetry-service.test.js +0 -182
- package/dist/services/cursor-usage-sync.test.d.ts +0 -1
- package/dist/services/cursor-usage-sync.test.js +0 -173
- package/dist/services/engineering-knowledge-graph.test.d.ts +0 -1
- package/dist/services/engineering-knowledge-graph.test.js +0 -76
- package/dist/services/model-pricing.test.d.ts +0 -1
- package/dist/services/model-pricing.test.js +0 -44
- package/dist/services/observed-savings.test.d.ts +0 -1
- package/dist/services/observed-savings.test.js +0 -37
- package/dist/services/score-history.test.d.ts +0 -1
- package/dist/services/score-history.test.js +0 -61
- package/dist/smoke.test.d.ts +0 -1
- package/dist/smoke.test.js +0 -17
- package/dist/storage/cache-cleanup.test.d.ts +0 -1
- package/dist/storage/cache-cleanup.test.js +0 -54
- package/dist/storage/context-telemetry.test.d.ts +0 -1
- package/dist/storage/context-telemetry.test.js +0 -80
- package/dist/storage/db.test.d.ts +0 -1
- package/dist/storage/db.test.js +0 -46
- package/dist/storage/fix-lessons.test.d.ts +0 -1
- package/dist/storage/fix-lessons.test.js +0 -61
- package/dist/storage/lessons.test.d.ts +0 -1
- package/dist/storage/lessons.test.js +0 -81
- package/dist/storage/local-encryption.test.d.ts +0 -1
- package/dist/storage/local-encryption.test.js +0 -34
- package/dist/storage/local-memory.test.d.ts +0 -1
- package/dist/storage/local-memory.test.js +0 -55
- package/dist/storage/share-memory.test.d.ts +0 -1
- package/dist/storage/share-memory.test.js +0 -34
- package/dist/storage/team-diagnostics.test.d.ts +0 -1
- package/dist/storage/team-diagnostics.test.js +0 -51
- package/dist/storage/team-scope.test.d.ts +0 -1
- package/dist/storage/team-scope.test.js +0 -22
- package/dist/storage/team-store.test.d.ts +0 -1
- package/dist/storage/team-store.test.js +0 -11
- package/dist/storage/team-sync-scope.test.d.ts +0 -1
- package/dist/storage/team-sync-scope.test.js +0 -100
- package/dist/storage/team-vector-store.test.d.ts +0 -1
- package/dist/storage/team-vector-store.test.js +0 -56
- package/dist/storage/telemetry-scope.test.d.ts +0 -1
- package/dist/storage/telemetry-scope.test.js +0 -38
- package/dist/task/thread.test.d.ts +0 -1
- package/dist/task/thread.test.js +0 -133
- package/dist/telemetry/telemetry.test.d.ts +0 -1
- package/dist/telemetry/telemetry.test.js +0 -64
- package/dist/types/index.test.d.ts +0 -1
- package/dist/types/index.test.js +0 -33
- package/dist/utils/command-line.test.d.ts +0 -1
- package/dist/utils/command-line.test.js +0 -8
- package/dist/utils/diff-removed.test.d.ts +0 -1
- package/dist/utils/diff-removed.test.js +0 -29
- package/dist/utils/diff.test.d.ts +0 -1
- package/dist/utils/diff.test.js +0 -38
- package/dist/utils/glob-paths.test.d.ts +0 -1
- package/dist/utils/glob-paths.test.js +0 -40
- package/dist/utils/profile.test.d.ts +0 -1
- package/dist/utils/profile.test.js +0 -68
- package/dist/utils/scanner.test.d.ts +0 -1
- package/dist/utils/scanner.test.js +0 -48
- package/dist/utils/scope.test.d.ts +0 -1
- package/dist/utils/scope.test.js +0 -38
|
@@ -1,635 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { verifyFindings } from './verifier.js';
|
|
3
|
-
// ── Test helpers ──
|
|
4
|
-
function makeFinding(overrides = {}) {
|
|
5
|
-
return {
|
|
6
|
-
category: 'god_class',
|
|
7
|
-
severity: 'high',
|
|
8
|
-
file: 'src/service.ts',
|
|
9
|
-
line: 10,
|
|
10
|
-
description: 'The UserService class has too many responsibilities',
|
|
11
|
-
suggestion: 'Split into smaller services',
|
|
12
|
-
confidence: 0.8,
|
|
13
|
-
...overrides,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
function makeFileFacts(overrides = {}) {
|
|
17
|
-
return {
|
|
18
|
-
path: 'src/service.ts',
|
|
19
|
-
language: 'typescript',
|
|
20
|
-
lineCount: 300,
|
|
21
|
-
classes: [{
|
|
22
|
-
name: 'UserService',
|
|
23
|
-
lineStart: 5,
|
|
24
|
-
lineEnd: 290,
|
|
25
|
-
methodCount: 12,
|
|
26
|
-
methods: ['find', 'create', 'update', 'delete', 'validate', 'transform', 'cache', 'notify', 'log', 'serialize', 'auth', 'batch'],
|
|
27
|
-
publicMethods: ['find', 'create', 'update', 'delete'],
|
|
28
|
-
lineCount: 285,
|
|
29
|
-
dependencies: ['Database', 'Logger'],
|
|
30
|
-
}],
|
|
31
|
-
functions: [{
|
|
32
|
-
name: 'processData',
|
|
33
|
-
lineStart: 10,
|
|
34
|
-
lineEnd: 80,
|
|
35
|
-
lineCount: 70,
|
|
36
|
-
paramCount: 5,
|
|
37
|
-
params: ['a', 'b', 'c', 'd', 'e'],
|
|
38
|
-
maxNesting: 4,
|
|
39
|
-
hasReturn: true,
|
|
40
|
-
isAsync: true,
|
|
41
|
-
isExported: true,
|
|
42
|
-
}],
|
|
43
|
-
imports: ['express', './types'],
|
|
44
|
-
exports: ['UserService'],
|
|
45
|
-
errorHandling: [
|
|
46
|
-
{ type: 'try-catch', lineStart: 20, isEmpty: false, strategy: 'throw' },
|
|
47
|
-
{ type: 'try-catch', lineStart: 50, isEmpty: true, strategy: 'ignore' },
|
|
48
|
-
],
|
|
49
|
-
testAssertions: 0,
|
|
50
|
-
hasTests: false,
|
|
51
|
-
...overrides,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
describe('Verifier', () => {
|
|
55
|
-
// ── File existence ──
|
|
56
|
-
describe('file existence check', () => {
|
|
57
|
-
it('should drop findings for files not in facts', () => {
|
|
58
|
-
const findings = [makeFinding({ file: 'src/nonexistent.ts' })];
|
|
59
|
-
const facts = [makeFileFacts()];
|
|
60
|
-
const result = verifyFindings(findings, facts);
|
|
61
|
-
expect(result).toHaveLength(0);
|
|
62
|
-
});
|
|
63
|
-
it('should accept findings for files that exist', () => {
|
|
64
|
-
const findings = [makeFinding()];
|
|
65
|
-
const facts = [makeFileFacts()];
|
|
66
|
-
const result = verifyFindings(findings, facts);
|
|
67
|
-
expect(result).toHaveLength(1);
|
|
68
|
-
expect(result[0].verified).toBe(true);
|
|
69
|
-
});
|
|
70
|
-
it('should handle path normalization (leading ./)', () => {
|
|
71
|
-
const findings = [makeFinding({ file: './src/service.ts' })];
|
|
72
|
-
const facts = [makeFileFacts()];
|
|
73
|
-
const result = verifyFindings(findings, facts);
|
|
74
|
-
expect(result).toHaveLength(1);
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
// ── Class/Struct findings (SOLID) ──
|
|
78
|
-
describe('class/struct-based verification', () => {
|
|
79
|
-
it('should verify god_class when class has many methods', () => {
|
|
80
|
-
const findings = [makeFinding({ category: 'god_class' })];
|
|
81
|
-
const facts = [makeFileFacts()];
|
|
82
|
-
const result = verifyFindings(findings, facts);
|
|
83
|
-
expect(result).toHaveLength(1);
|
|
84
|
-
expect(result[0].verified).toBe(true);
|
|
85
|
-
expect(result[0].verificationNotes).toContain('12 methods');
|
|
86
|
-
});
|
|
87
|
-
it('should reject god_class when class is small', () => {
|
|
88
|
-
const findings = [makeFinding({ category: 'god_class' })];
|
|
89
|
-
const facts = [makeFileFacts({
|
|
90
|
-
classes: [{
|
|
91
|
-
name: 'UserService',
|
|
92
|
-
lineStart: 5,
|
|
93
|
-
lineEnd: 30,
|
|
94
|
-
methodCount: 3,
|
|
95
|
-
methods: ['find', 'create', 'update'],
|
|
96
|
-
publicMethods: ['find', 'create'],
|
|
97
|
-
lineCount: 25,
|
|
98
|
-
dependencies: [],
|
|
99
|
-
}],
|
|
100
|
-
})];
|
|
101
|
-
const result = verifyFindings(findings, facts);
|
|
102
|
-
expect(result).toHaveLength(0);
|
|
103
|
-
});
|
|
104
|
-
it('should accept god_class for Go structs', () => {
|
|
105
|
-
const findings = [makeFinding({
|
|
106
|
-
category: 'god_class',
|
|
107
|
-
file: 'pkg/server.go',
|
|
108
|
-
description: 'The Server struct has too many responsibilities',
|
|
109
|
-
})];
|
|
110
|
-
const facts = [makeFileFacts({
|
|
111
|
-
path: 'pkg/server.go',
|
|
112
|
-
language: 'go',
|
|
113
|
-
classes: [],
|
|
114
|
-
structs: [{
|
|
115
|
-
name: 'Server',
|
|
116
|
-
lineStart: 5,
|
|
117
|
-
lineEnd: 250,
|
|
118
|
-
fieldCount: 8,
|
|
119
|
-
methodCount: 10,
|
|
120
|
-
methods: ['Start', 'Stop', 'Handle', 'Route', 'Auth', 'Log', 'Cache', 'Validate', 'Transform', 'Serialize'],
|
|
121
|
-
lineCount: 245,
|
|
122
|
-
embeds: [],
|
|
123
|
-
}],
|
|
124
|
-
})];
|
|
125
|
-
const result = verifyFindings(findings, facts);
|
|
126
|
-
expect(result).toHaveLength(1);
|
|
127
|
-
expect(result[0].verified).toBe(true);
|
|
128
|
-
});
|
|
129
|
-
it('should accept Go module-level god_class when file has many functions', () => {
|
|
130
|
-
const findings = [makeFinding({
|
|
131
|
-
category: 'god_class',
|
|
132
|
-
file: 'pkg/utils.go',
|
|
133
|
-
description: 'This module has too many responsibilities',
|
|
134
|
-
})];
|
|
135
|
-
const facts = [makeFileFacts({
|
|
136
|
-
path: 'pkg/utils.go',
|
|
137
|
-
language: 'go',
|
|
138
|
-
classes: [],
|
|
139
|
-
structs: [],
|
|
140
|
-
functions: Array.from({ length: 15 }, (_, i) => ({
|
|
141
|
-
name: `func${i}`,
|
|
142
|
-
lineStart: i * 20,
|
|
143
|
-
lineEnd: i * 20 + 15,
|
|
144
|
-
lineCount: 15,
|
|
145
|
-
paramCount: 2,
|
|
146
|
-
params: ['a', 'b'],
|
|
147
|
-
maxNesting: 2,
|
|
148
|
-
hasReturn: true,
|
|
149
|
-
isAsync: false,
|
|
150
|
-
isExported: true,
|
|
151
|
-
})),
|
|
152
|
-
})];
|
|
153
|
-
const result = verifyFindings(findings, facts);
|
|
154
|
-
expect(result).toHaveLength(1);
|
|
155
|
-
expect(result[0].verified).toBe(true);
|
|
156
|
-
expect(result[0].verificationNotes).toContain('15 functions');
|
|
157
|
-
});
|
|
158
|
-
it('should reject when entity name not found in file', () => {
|
|
159
|
-
const findings = [makeFinding({
|
|
160
|
-
category: 'srp_violation',
|
|
161
|
-
description: 'The NonExistentClass has too many responsibilities',
|
|
162
|
-
})];
|
|
163
|
-
const facts = [makeFileFacts()];
|
|
164
|
-
const result = verifyFindings(findings, facts);
|
|
165
|
-
// Should still verify since file has classes with confidence >= 0.4
|
|
166
|
-
expect(result).toHaveLength(1);
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
// ── Function findings ──
|
|
170
|
-
describe('function-based verification', () => {
|
|
171
|
-
it('should verify god_function when function is long', () => {
|
|
172
|
-
const findings = [makeFinding({
|
|
173
|
-
category: 'god_function',
|
|
174
|
-
description: 'processData is too long and complex',
|
|
175
|
-
})];
|
|
176
|
-
const facts = [makeFileFacts()];
|
|
177
|
-
const result = verifyFindings(findings, facts);
|
|
178
|
-
expect(result).toHaveLength(1);
|
|
179
|
-
expect(result[0].verified).toBe(true);
|
|
180
|
-
});
|
|
181
|
-
it('should reject god_function when function is short', () => {
|
|
182
|
-
const findings = [makeFinding({
|
|
183
|
-
category: 'god_function',
|
|
184
|
-
description: 'processData is too complex',
|
|
185
|
-
})];
|
|
186
|
-
const facts = [makeFileFacts({
|
|
187
|
-
functions: [{
|
|
188
|
-
name: 'processData',
|
|
189
|
-
lineStart: 10,
|
|
190
|
-
lineEnd: 25,
|
|
191
|
-
lineCount: 15,
|
|
192
|
-
paramCount: 2,
|
|
193
|
-
params: ['a', 'b'],
|
|
194
|
-
maxNesting: 1,
|
|
195
|
-
hasReturn: true,
|
|
196
|
-
isAsync: false,
|
|
197
|
-
isExported: true,
|
|
198
|
-
}],
|
|
199
|
-
})];
|
|
200
|
-
const result = verifyFindings(findings, facts);
|
|
201
|
-
expect(result).toHaveLength(0);
|
|
202
|
-
});
|
|
203
|
-
it('should verify long_params when function has many params', () => {
|
|
204
|
-
const findings = [makeFinding({
|
|
205
|
-
category: 'long_params',
|
|
206
|
-
description: 'processData has too many parameters',
|
|
207
|
-
})];
|
|
208
|
-
const facts = [makeFileFacts()];
|
|
209
|
-
const result = verifyFindings(findings, facts);
|
|
210
|
-
expect(result).toHaveLength(1);
|
|
211
|
-
expect(result[0].verified).toBe(true);
|
|
212
|
-
});
|
|
213
|
-
it('should reject long_params when function has few params', () => {
|
|
214
|
-
const findings = [makeFinding({
|
|
215
|
-
category: 'long_params',
|
|
216
|
-
description: 'processData has too many parameters',
|
|
217
|
-
})];
|
|
218
|
-
const facts = [makeFileFacts({
|
|
219
|
-
functions: [{
|
|
220
|
-
name: 'processData',
|
|
221
|
-
lineStart: 10,
|
|
222
|
-
lineEnd: 50,
|
|
223
|
-
lineCount: 40,
|
|
224
|
-
paramCount: 2,
|
|
225
|
-
params: ['a', 'b'],
|
|
226
|
-
maxNesting: 2,
|
|
227
|
-
hasReturn: true,
|
|
228
|
-
isAsync: false,
|
|
229
|
-
isExported: true,
|
|
230
|
-
}],
|
|
231
|
-
})];
|
|
232
|
-
const result = verifyFindings(findings, facts);
|
|
233
|
-
expect(result).toHaveLength(0);
|
|
234
|
-
});
|
|
235
|
-
it('should verify complex_conditional when nesting is deep', () => {
|
|
236
|
-
const findings = [makeFinding({
|
|
237
|
-
category: 'complex_conditional',
|
|
238
|
-
description: 'processData has deeply nested conditionals',
|
|
239
|
-
})];
|
|
240
|
-
const facts = [makeFileFacts()];
|
|
241
|
-
const result = verifyFindings(findings, facts);
|
|
242
|
-
expect(result).toHaveLength(1);
|
|
243
|
-
expect(result[0].verified).toBe(true);
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
// ── Error handling findings ──
|
|
247
|
-
describe('error handling verification', () => {
|
|
248
|
-
it('should verify empty_catch when empty catches exist', () => {
|
|
249
|
-
const findings = [makeFinding({
|
|
250
|
-
category: 'empty_catch',
|
|
251
|
-
description: 'Empty catch block silently swallows errors',
|
|
252
|
-
})];
|
|
253
|
-
const facts = [makeFileFacts()];
|
|
254
|
-
const result = verifyFindings(findings, facts);
|
|
255
|
-
expect(result).toHaveLength(1);
|
|
256
|
-
expect(result[0].verified).toBe(true);
|
|
257
|
-
});
|
|
258
|
-
it('should reject empty_catch when no empty catches exist', () => {
|
|
259
|
-
const findings = [makeFinding({
|
|
260
|
-
category: 'empty_catch',
|
|
261
|
-
description: 'Empty catch block',
|
|
262
|
-
})];
|
|
263
|
-
const facts = [makeFileFacts({
|
|
264
|
-
errorHandling: [
|
|
265
|
-
{ type: 'try-catch', lineStart: 10, isEmpty: false, strategy: 'throw' },
|
|
266
|
-
],
|
|
267
|
-
})];
|
|
268
|
-
const result = verifyFindings(findings, facts);
|
|
269
|
-
expect(result).toHaveLength(0);
|
|
270
|
-
});
|
|
271
|
-
it('should verify error_inconsistency when multiple strategies exist', () => {
|
|
272
|
-
const findings = [makeFinding({
|
|
273
|
-
category: 'error_inconsistency',
|
|
274
|
-
description: 'Mixed error handling strategies',
|
|
275
|
-
})];
|
|
276
|
-
const facts = [makeFileFacts()]; // Has 'throw' and 'ignore' strategies
|
|
277
|
-
const result = verifyFindings(findings, facts);
|
|
278
|
-
expect(result).toHaveLength(1);
|
|
279
|
-
expect(result[0].verified).toBe(true);
|
|
280
|
-
});
|
|
281
|
-
});
|
|
282
|
-
// ── Concurrency findings ──
|
|
283
|
-
describe('concurrency verification', () => {
|
|
284
|
-
const goFacts = () => makeFileFacts({
|
|
285
|
-
path: 'pkg/worker.go',
|
|
286
|
-
language: 'go',
|
|
287
|
-
goroutines: 3,
|
|
288
|
-
channels: 2,
|
|
289
|
-
mutexes: 1,
|
|
290
|
-
defers: 2,
|
|
291
|
-
});
|
|
292
|
-
it('should verify race_condition when concurrency constructs exist', () => {
|
|
293
|
-
const findings = [makeFinding({
|
|
294
|
-
category: 'race_condition',
|
|
295
|
-
file: 'pkg/worker.go',
|
|
296
|
-
description: 'Potential race condition',
|
|
297
|
-
confidence: 0.6,
|
|
298
|
-
})];
|
|
299
|
-
const result = verifyFindings(findings, [goFacts()]);
|
|
300
|
-
expect(result).toHaveLength(1);
|
|
301
|
-
expect(result[0].verified).toBe(true);
|
|
302
|
-
});
|
|
303
|
-
it('should reject goroutine_leak when no goroutines exist', () => {
|
|
304
|
-
const findings = [makeFinding({
|
|
305
|
-
category: 'goroutine_leak',
|
|
306
|
-
file: 'pkg/worker.go',
|
|
307
|
-
description: 'Goroutine leak detected',
|
|
308
|
-
confidence: 0.7,
|
|
309
|
-
})];
|
|
310
|
-
const facts = goFacts();
|
|
311
|
-
facts.goroutines = 0;
|
|
312
|
-
const result = verifyFindings(findings, [facts]);
|
|
313
|
-
expect(result).toHaveLength(0);
|
|
314
|
-
});
|
|
315
|
-
it('should reject channel_misuse when no channels exist', () => {
|
|
316
|
-
const findings = [makeFinding({
|
|
317
|
-
category: 'channel_misuse',
|
|
318
|
-
file: 'pkg/worker.go',
|
|
319
|
-
description: 'Channel misuse detected',
|
|
320
|
-
confidence: 0.7,
|
|
321
|
-
})];
|
|
322
|
-
const facts = goFacts();
|
|
323
|
-
facts.channels = 0;
|
|
324
|
-
const result = verifyFindings(findings, [facts]);
|
|
325
|
-
expect(result).toHaveLength(0);
|
|
326
|
-
});
|
|
327
|
-
it('should reject concurrency finding when no concurrency exists', () => {
|
|
328
|
-
const findings = [makeFinding({
|
|
329
|
-
category: 'race_condition',
|
|
330
|
-
file: 'pkg/worker.go',
|
|
331
|
-
description: 'Race condition',
|
|
332
|
-
confidence: 0.8,
|
|
333
|
-
})];
|
|
334
|
-
const facts = goFacts();
|
|
335
|
-
facts.goroutines = 0;
|
|
336
|
-
facts.channels = 0;
|
|
337
|
-
facts.mutexes = 0;
|
|
338
|
-
facts.functions = facts.functions.map(f => ({ ...f, isAsync: false }));
|
|
339
|
-
const result = verifyFindings(findings, [facts]);
|
|
340
|
-
expect(result).toHaveLength(0);
|
|
341
|
-
});
|
|
342
|
-
});
|
|
343
|
-
// ── Interface findings ──
|
|
344
|
-
describe('interface verification', () => {
|
|
345
|
-
it('should verify ISP violation on large interface', () => {
|
|
346
|
-
const findings = [makeFinding({
|
|
347
|
-
category: 'isp_violation_interface',
|
|
348
|
-
file: 'pkg/store.go',
|
|
349
|
-
description: 'Store interface has too many methods',
|
|
350
|
-
confidence: 0.8,
|
|
351
|
-
})];
|
|
352
|
-
const facts = [makeFileFacts({
|
|
353
|
-
path: 'pkg/store.go',
|
|
354
|
-
language: 'go',
|
|
355
|
-
interfaces: [{
|
|
356
|
-
name: 'Store',
|
|
357
|
-
lineStart: 5,
|
|
358
|
-
methodCount: 8,
|
|
359
|
-
methods: ['Get', 'Set', 'Delete', 'List', 'Close', 'Watch', 'Backup', 'Restore'],
|
|
360
|
-
}],
|
|
361
|
-
})];
|
|
362
|
-
const result = verifyFindings(findings, facts);
|
|
363
|
-
expect(result).toHaveLength(1);
|
|
364
|
-
expect(result[0].verified).toBe(true);
|
|
365
|
-
});
|
|
366
|
-
it('should reject ISP violation when no interfaces exist', () => {
|
|
367
|
-
const findings = [makeFinding({
|
|
368
|
-
category: 'isp_violation_interface',
|
|
369
|
-
file: 'pkg/store.go',
|
|
370
|
-
description: 'Interface has too many methods',
|
|
371
|
-
})];
|
|
372
|
-
const facts = [makeFileFacts({
|
|
373
|
-
path: 'pkg/store.go',
|
|
374
|
-
interfaces: [],
|
|
375
|
-
})];
|
|
376
|
-
const result = verifyFindings(findings, facts);
|
|
377
|
-
expect(result).toHaveLength(0);
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
// ── Test findings ──
|
|
381
|
-
describe('test verification', () => {
|
|
382
|
-
it('should verify missing_test for substantial code files', () => {
|
|
383
|
-
const findings = [makeFinding({
|
|
384
|
-
category: 'missing_test',
|
|
385
|
-
description: 'No tests for this module',
|
|
386
|
-
})];
|
|
387
|
-
const facts = [makeFileFacts({
|
|
388
|
-
functions: [
|
|
389
|
-
{ name: 'processData', lineStart: 10, lineEnd: 80, lineCount: 70, paramCount: 5, params: ['a', 'b', 'c', 'd', 'e'], maxNesting: 4, hasReturn: true, isAsync: true, isExported: true },
|
|
390
|
-
{ name: 'helperFn', lineStart: 85, lineEnd: 100, lineCount: 15, paramCount: 1, params: ['x'], maxNesting: 1, hasReturn: true, isAsync: false, isExported: false },
|
|
391
|
-
],
|
|
392
|
-
})]; // hasTests: false, 300 lines, 2 functions
|
|
393
|
-
const result = verifyFindings(findings, facts);
|
|
394
|
-
expect(result).toHaveLength(1);
|
|
395
|
-
expect(result[0].verified).toBe(true);
|
|
396
|
-
});
|
|
397
|
-
it('should reject missing_test when file already has tests', () => {
|
|
398
|
-
const findings = [makeFinding({
|
|
399
|
-
category: 'missing_test',
|
|
400
|
-
description: 'No tests',
|
|
401
|
-
})];
|
|
402
|
-
const facts = [makeFileFacts({ hasTests: true })];
|
|
403
|
-
const result = verifyFindings(findings, facts);
|
|
404
|
-
expect(result).toHaveLength(0);
|
|
405
|
-
});
|
|
406
|
-
it('should reject missing_test for trivial files', () => {
|
|
407
|
-
const findings = [makeFinding({
|
|
408
|
-
category: 'missing_test',
|
|
409
|
-
description: 'No tests',
|
|
410
|
-
})];
|
|
411
|
-
const facts = [makeFileFacts({ lineCount: 20, functions: [] })];
|
|
412
|
-
const result = verifyFindings(findings, facts);
|
|
413
|
-
expect(result).toHaveLength(0);
|
|
414
|
-
});
|
|
415
|
-
});
|
|
416
|
-
// ── File-level categories ──
|
|
417
|
-
describe('file-level verification', () => {
|
|
418
|
-
it('should verify long_file when file exceeds 300 lines', () => {
|
|
419
|
-
const findings = [makeFinding({ category: 'long_file' })];
|
|
420
|
-
const facts = [makeFileFacts({ lineCount: 500 })];
|
|
421
|
-
const result = verifyFindings(findings, facts);
|
|
422
|
-
expect(result).toHaveLength(1);
|
|
423
|
-
expect(result[0].verified).toBe(true);
|
|
424
|
-
});
|
|
425
|
-
it('should reject long_file when file is short', () => {
|
|
426
|
-
const findings = [makeFinding({ category: 'long_file' })];
|
|
427
|
-
const facts = [makeFileFacts({ lineCount: 100 })];
|
|
428
|
-
const result = verifyFindings(findings, facts);
|
|
429
|
-
expect(result).toHaveLength(0);
|
|
430
|
-
});
|
|
431
|
-
it('should verify magic_number when many magic numbers detected', () => {
|
|
432
|
-
const findings = [makeFinding({ category: 'magic_number' })];
|
|
433
|
-
const facts = [makeFileFacts({ magicNumbers: 10 })];
|
|
434
|
-
const result = verifyFindings(findings, facts);
|
|
435
|
-
expect(result).toHaveLength(1);
|
|
436
|
-
});
|
|
437
|
-
it('should reject magic_number when few magic numbers detected', () => {
|
|
438
|
-
const findings = [makeFinding({ category: 'magic_number' })];
|
|
439
|
-
const facts = [makeFileFacts({ magicNumbers: 1 })];
|
|
440
|
-
const result = verifyFindings(findings, facts);
|
|
441
|
-
expect(result).toHaveLength(0);
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
// ── Structurally-verified categories ──
|
|
445
|
-
// After verifier hardening, these categories use entity names, cross-file
|
|
446
|
-
// checks, or raised confidence floors — not just confidence >= 0.3.
|
|
447
|
-
describe('structurally-verified categories', () => {
|
|
448
|
-
// Tier 1: Entity-name required — accepts when entity name matches
|
|
449
|
-
it('should accept feature_envy when entity name exists in file', () => {
|
|
450
|
-
const findings = [makeFinding({
|
|
451
|
-
category: 'feature_envy',
|
|
452
|
-
description: 'The processData function accesses too many external modules',
|
|
453
|
-
confidence: 0.5,
|
|
454
|
-
})];
|
|
455
|
-
const facts = [makeFileFacts()];
|
|
456
|
-
const result = verifyFindings(findings, facts);
|
|
457
|
-
expect(result).toHaveLength(1);
|
|
458
|
-
});
|
|
459
|
-
it('should reject feature_envy with no entity name and low confidence', () => {
|
|
460
|
-
const findings = [makeFinding({
|
|
461
|
-
category: 'feature_envy',
|
|
462
|
-
description: 'Some function accesses external modules',
|
|
463
|
-
confidence: 0.3,
|
|
464
|
-
})];
|
|
465
|
-
const facts = [makeFileFacts()];
|
|
466
|
-
const result = verifyFindings(findings, facts);
|
|
467
|
-
expect(result).toHaveLength(0); // No entity name → needs confidence >= 0.6
|
|
468
|
-
});
|
|
469
|
-
// Tier 2: dead_code — needs entity unreferenced externally
|
|
470
|
-
it('should accept dead_code when entity is unreferenced', () => {
|
|
471
|
-
const findings = [makeFinding({
|
|
472
|
-
category: 'dead_code',
|
|
473
|
-
description: 'processData is never called',
|
|
474
|
-
confidence: 0.5,
|
|
475
|
-
})];
|
|
476
|
-
// Only one file — processData can't be imported by other files
|
|
477
|
-
const facts = [makeFileFacts()];
|
|
478
|
-
const result = verifyFindings(findings, facts);
|
|
479
|
-
expect(result).toHaveLength(1);
|
|
480
|
-
});
|
|
481
|
-
it('should reject dead_code when entity is imported by another file', () => {
|
|
482
|
-
const findings = [makeFinding({
|
|
483
|
-
category: 'dead_code',
|
|
484
|
-
description: 'processData is never called',
|
|
485
|
-
confidence: 0.9,
|
|
486
|
-
})];
|
|
487
|
-
const facts = [
|
|
488
|
-
makeFileFacts(),
|
|
489
|
-
makeFileFacts({
|
|
490
|
-
path: 'src/consumer.ts',
|
|
491
|
-
imports: ['./service', 'processData'], // References the entity
|
|
492
|
-
}),
|
|
493
|
-
];
|
|
494
|
-
const result = verifyFindings(findings, facts);
|
|
495
|
-
expect(result).toHaveLength(0); // Entity is referenced — not dead code
|
|
496
|
-
});
|
|
497
|
-
// Tier 2: naming_convention — checks actual language rules
|
|
498
|
-
it('should accept naming_convention when name violates rules', () => {
|
|
499
|
-
const findings = [makeFinding({
|
|
500
|
-
category: 'naming_convention',
|
|
501
|
-
file: 'pkg/utils.go',
|
|
502
|
-
description: 'get_user_name uses snake_case instead of MixedCaps',
|
|
503
|
-
confidence: 0.5,
|
|
504
|
-
})];
|
|
505
|
-
const facts = [makeFileFacts({
|
|
506
|
-
path: 'pkg/utils.go',
|
|
507
|
-
language: 'go',
|
|
508
|
-
functions: [{
|
|
509
|
-
name: 'get_user_name',
|
|
510
|
-
lineStart: 10, lineEnd: 30, lineCount: 20,
|
|
511
|
-
paramCount: 1, params: ['id'],
|
|
512
|
-
maxNesting: 1, hasReturn: true, isAsync: false, isExported: false,
|
|
513
|
-
}],
|
|
514
|
-
})];
|
|
515
|
-
const result = verifyFindings(findings, facts);
|
|
516
|
-
expect(result).toHaveLength(1);
|
|
517
|
-
expect(result[0].verified).toBe(true);
|
|
518
|
-
});
|
|
519
|
-
it('should reject naming_convention when name follows rules', () => {
|
|
520
|
-
const findings = [makeFinding({
|
|
521
|
-
category: 'naming_convention',
|
|
522
|
-
description: 'processData naming issue',
|
|
523
|
-
confidence: 0.8,
|
|
524
|
-
})];
|
|
525
|
-
const facts = [makeFileFacts()]; // processData is camelCase — correct for TS
|
|
526
|
-
const result = verifyFindings(findings, facts);
|
|
527
|
-
expect(result).toHaveLength(0); // Name follows conventions → FP
|
|
528
|
-
});
|
|
529
|
-
// Tier 2: performance — needs non-trivial function
|
|
530
|
-
it('should accept performance when function is substantial', () => {
|
|
531
|
-
const findings = [makeFinding({
|
|
532
|
-
category: 'performance',
|
|
533
|
-
description: 'processData has O(n²) complexity',
|
|
534
|
-
confidence: 0.5,
|
|
535
|
-
})];
|
|
536
|
-
const facts = [makeFileFacts()]; // processData is 70 lines
|
|
537
|
-
const result = verifyFindings(findings, facts);
|
|
538
|
-
expect(result).toHaveLength(1);
|
|
539
|
-
});
|
|
540
|
-
// Tier 3: dry_violation — needs cross-file similarity
|
|
541
|
-
it('should accept dry_violation when similar function exists in another file', () => {
|
|
542
|
-
const findings = [makeFinding({
|
|
543
|
-
category: 'dry_violation',
|
|
544
|
-
description: 'processData is duplicated across files',
|
|
545
|
-
confidence: 0.5,
|
|
546
|
-
})];
|
|
547
|
-
const facts = [
|
|
548
|
-
makeFileFacts(),
|
|
549
|
-
makeFileFacts({
|
|
550
|
-
path: 'src/other.ts',
|
|
551
|
-
functions: [{
|
|
552
|
-
name: 'processData', // Same name = similar
|
|
553
|
-
lineStart: 10, lineEnd: 80, lineCount: 70,
|
|
554
|
-
paramCount: 5, params: ['a', 'b', 'c', 'd', 'e'],
|
|
555
|
-
maxNesting: 3, hasReturn: true, isAsync: true, isExported: true,
|
|
556
|
-
}],
|
|
557
|
-
}),
|
|
558
|
-
];
|
|
559
|
-
const result = verifyFindings(findings, facts);
|
|
560
|
-
expect(result).toHaveLength(1);
|
|
561
|
-
});
|
|
562
|
-
it('should reject dry_violation when no similar function exists', () => {
|
|
563
|
-
const findings = [makeFinding({
|
|
564
|
-
category: 'dry_violation',
|
|
565
|
-
description: 'processData is duplicated',
|
|
566
|
-
confidence: 0.5,
|
|
567
|
-
})];
|
|
568
|
-
const facts = [makeFileFacts()]; // Only one file — no cross-file match
|
|
569
|
-
const result = verifyFindings(findings, facts);
|
|
570
|
-
expect(result).toHaveLength(0);
|
|
571
|
-
});
|
|
572
|
-
// Tier 4: Confidence floor raised to 0.5
|
|
573
|
-
it('should accept architecture with confidence >= 0.5', () => {
|
|
574
|
-
const findings = [makeFinding({ category: 'architecture', confidence: 0.6 })];
|
|
575
|
-
const facts = [makeFileFacts()];
|
|
576
|
-
const result = verifyFindings(findings, facts);
|
|
577
|
-
expect(result).toHaveLength(1);
|
|
578
|
-
});
|
|
579
|
-
it('should reject architecture with confidence < 0.5', () => {
|
|
580
|
-
const findings = [makeFinding({ category: 'architecture', confidence: 0.4 })];
|
|
581
|
-
const facts = [makeFileFacts()];
|
|
582
|
-
const result = verifyFindings(findings, facts);
|
|
583
|
-
expect(result).toHaveLength(0);
|
|
584
|
-
});
|
|
585
|
-
});
|
|
586
|
-
// ── Resource leak (Go-specific) ──
|
|
587
|
-
describe('resource leak verification', () => {
|
|
588
|
-
it('should verify Go resource leak when resource imports present', () => {
|
|
589
|
-
const findings = [makeFinding({
|
|
590
|
-
category: 'resource_leak',
|
|
591
|
-
file: 'pkg/db.go',
|
|
592
|
-
confidence: 0.6,
|
|
593
|
-
})];
|
|
594
|
-
const facts = [makeFileFacts({
|
|
595
|
-
path: 'pkg/db.go',
|
|
596
|
-
language: 'go',
|
|
597
|
-
imports: ['database/sql', 'net/http'],
|
|
598
|
-
})];
|
|
599
|
-
const result = verifyFindings(findings, facts);
|
|
600
|
-
expect(result).toHaveLength(1);
|
|
601
|
-
expect(result[0].verified).toBe(true);
|
|
602
|
-
});
|
|
603
|
-
it('should reject Go resource leak when no resource imports', () => {
|
|
604
|
-
const findings = [makeFinding({
|
|
605
|
-
category: 'resource_leak',
|
|
606
|
-
file: 'pkg/util.go',
|
|
607
|
-
confidence: 0.6,
|
|
608
|
-
})];
|
|
609
|
-
const facts = [makeFileFacts({
|
|
610
|
-
path: 'pkg/util.go',
|
|
611
|
-
language: 'go',
|
|
612
|
-
imports: ['fmt', 'strings'],
|
|
613
|
-
})];
|
|
614
|
-
const result = verifyFindings(findings, facts);
|
|
615
|
-
expect(result).toHaveLength(0);
|
|
616
|
-
});
|
|
617
|
-
});
|
|
618
|
-
// ── Multiple findings batch ──
|
|
619
|
-
describe('batch verification', () => {
|
|
620
|
-
it('should process multiple findings and filter correctly', () => {
|
|
621
|
-
const findings = [
|
|
622
|
-
makeFinding({ category: 'god_class' }), // Should pass (12 methods)
|
|
623
|
-
makeFinding({ category: 'god_function', file: 'nonexistent.ts' }), // Should fail (no file)
|
|
624
|
-
makeFinding({ category: 'long_file' }), // Should fail (300 lines, need >300)
|
|
625
|
-
makeFinding({ category: 'magic_number' }), // Should fail (no magicNumbers set)
|
|
626
|
-
makeFinding({ category: 'architecture', confidence: 0.1 }), // Should fail (below 0.5 floor)
|
|
627
|
-
makeFinding({ category: 'architecture', confidence: 0.6 }), // Should pass (above 0.5 floor)
|
|
628
|
-
];
|
|
629
|
-
const facts = [makeFileFacts()];
|
|
630
|
-
const result = verifyFindings(findings, facts);
|
|
631
|
-
const verified = result.filter(r => r.verified);
|
|
632
|
-
expect(verified.length).toBeGreaterThanOrEqual(2); // god_class, architecture(0.6)
|
|
633
|
-
});
|
|
634
|
-
});
|
|
635
|
-
});
|
package/dist/discovery.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|