@rigour-labs/core 2.9.4 → 2.11.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/dist/index.js +4 -0
- package/dist/pattern-index/embeddings.d.ts +19 -0
- package/dist/pattern-index/embeddings.js +78 -0
- package/dist/pattern-index/index.d.ts +12 -0
- package/dist/pattern-index/index.js +17 -0
- package/dist/pattern-index/indexer.d.ts +127 -0
- package/dist/pattern-index/indexer.js +891 -0
- package/dist/pattern-index/indexer.test.d.ts +6 -0
- package/dist/pattern-index/indexer.test.js +188 -0
- package/dist/pattern-index/matcher.d.ts +106 -0
- package/dist/pattern-index/matcher.js +376 -0
- package/dist/pattern-index/matcher.test.d.ts +6 -0
- package/dist/pattern-index/matcher.test.js +238 -0
- package/dist/pattern-index/overrides.d.ts +64 -0
- package/dist/pattern-index/overrides.js +196 -0
- package/dist/pattern-index/security.d.ts +25 -0
- package/dist/pattern-index/security.js +127 -0
- package/dist/pattern-index/staleness.d.ts +71 -0
- package/dist/pattern-index/staleness.js +381 -0
- package/dist/pattern-index/staleness.test.d.ts +6 -0
- package/dist/pattern-index/staleness.test.js +211 -0
- package/dist/pattern-index/types.d.ts +221 -0
- package/dist/pattern-index/types.js +7 -0
- package/package.json +14 -1
- package/src/index.ts +4 -0
- package/src/pattern-index/embeddings.ts +84 -0
- package/src/pattern-index/index.ts +59 -0
- package/src/pattern-index/indexer.test.ts +276 -0
- package/src/pattern-index/indexer.ts +1022 -0
- package/src/pattern-index/matcher.test.ts +293 -0
- package/src/pattern-index/matcher.ts +493 -0
- package/src/pattern-index/overrides.ts +235 -0
- package/src/pattern-index/security.ts +151 -0
- package/src/pattern-index/staleness.test.ts +313 -0
- package/src/pattern-index/staleness.ts +438 -0
- package/src/pattern-index/types.ts +339 -0
- package/vitest.config.ts +7 -0
- package/vitest.setup.ts +30 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern Index - Types
|
|
3
|
+
*
|
|
4
|
+
* Core type definitions for the Pattern Index system.
|
|
5
|
+
* Rigour's Pattern Index prevents AI from reinventing existing code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* All supported pattern types that can be indexed.
|
|
10
|
+
* Organized by category for clarity.
|
|
11
|
+
*/
|
|
12
|
+
export type PatternType =
|
|
13
|
+
// === CODE PATTERNS ===
|
|
14
|
+
| 'function' // Standalone functions, utilities
|
|
15
|
+
| 'class' // Classes
|
|
16
|
+
| 'method' // Class methods (indexed separately for reuse)
|
|
17
|
+
| 'component' // React/Vue/Svelte components
|
|
18
|
+
| 'hook' // React hooks (useX)
|
|
19
|
+
| 'decorator' // Python/TS decorators
|
|
20
|
+
| 'middleware' // Express/FastAPI middleware
|
|
21
|
+
|
|
22
|
+
// === DATA PATTERNS ===
|
|
23
|
+
| 'type' // TypeScript types
|
|
24
|
+
| 'interface' // TypeScript interfaces
|
|
25
|
+
| 'schema' // Zod, Yup, JSON Schema validators
|
|
26
|
+
| 'model' // Database models (Prisma, SQLAlchemy, etc.)
|
|
27
|
+
| 'enum' // Enumerations
|
|
28
|
+
|
|
29
|
+
// === CONFIGURATION ===
|
|
30
|
+
| 'constant' // Constants, magic values
|
|
31
|
+
| 'config' // Configuration objects
|
|
32
|
+
| 'env' // Environment variable patterns
|
|
33
|
+
|
|
34
|
+
// === API PATTERNS ===
|
|
35
|
+
| 'route' // API routes/endpoints
|
|
36
|
+
| 'handler' // Route handlers
|
|
37
|
+
| 'resolver' // GraphQL resolvers
|
|
38
|
+
| 'rpc' // tRPC procedures
|
|
39
|
+
|
|
40
|
+
// === STATE PATTERNS ===
|
|
41
|
+
| 'store' // State stores (Zustand, Redux)
|
|
42
|
+
| 'reducer' // Redux reducers
|
|
43
|
+
| 'action' // Actions/mutations
|
|
44
|
+
| 'selector' // State selectors
|
|
45
|
+
|
|
46
|
+
// === ERROR HANDLING ===
|
|
47
|
+
| 'error' // Custom error classes
|
|
48
|
+
| 'exception' // Exception types
|
|
49
|
+
|
|
50
|
+
// === TESTING ===
|
|
51
|
+
| 'mock' // Mock objects/functions
|
|
52
|
+
| 'fixture' // Test fixtures
|
|
53
|
+
| 'factory' // Test factories
|
|
54
|
+
|
|
55
|
+
// === INFRASTRUCTURE ===
|
|
56
|
+
| 'command' // CLI commands
|
|
57
|
+
| 'task' // Background tasks/jobs
|
|
58
|
+
| 'event' // Event types/handlers
|
|
59
|
+
| 'protocol'; // Python protocols, abstract classes
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A single indexed pattern entry.
|
|
63
|
+
*/
|
|
64
|
+
export interface PatternEntry {
|
|
65
|
+
/** Unique identifier (hash of file + name) */
|
|
66
|
+
id: string;
|
|
67
|
+
|
|
68
|
+
/** The type of pattern */
|
|
69
|
+
type: PatternType;
|
|
70
|
+
|
|
71
|
+
/** Name of the pattern (e.g., "formatDate") */
|
|
72
|
+
name: string;
|
|
73
|
+
|
|
74
|
+
/** Relative path to the file */
|
|
75
|
+
file: string;
|
|
76
|
+
|
|
77
|
+
/** Line number where the pattern is defined */
|
|
78
|
+
line: number;
|
|
79
|
+
|
|
80
|
+
/** End line number */
|
|
81
|
+
endLine: number;
|
|
82
|
+
|
|
83
|
+
/** Function/method signature if applicable */
|
|
84
|
+
signature: string;
|
|
85
|
+
|
|
86
|
+
/** Description from JSDoc/docstring */
|
|
87
|
+
description: string;
|
|
88
|
+
|
|
89
|
+
/** Extracted semantic keywords for matching */
|
|
90
|
+
keywords: string[];
|
|
91
|
+
|
|
92
|
+
/** Content hash for change detection */
|
|
93
|
+
hash: string;
|
|
94
|
+
|
|
95
|
+
/** Is this pattern exported? */
|
|
96
|
+
exported: boolean;
|
|
97
|
+
|
|
98
|
+
/** How many files import this pattern */
|
|
99
|
+
usageCount: number; // How many files import this?
|
|
100
|
+
|
|
101
|
+
/** User-defined category/grouping */
|
|
102
|
+
category?: string; // User-defined grouping
|
|
103
|
+
embedding?: number[]; // Vector embedding for semantic search
|
|
104
|
+
|
|
105
|
+
/** Last indexed timestamp */
|
|
106
|
+
indexedAt: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The complete pattern index structure.
|
|
111
|
+
*/
|
|
112
|
+
export interface PatternIndex {
|
|
113
|
+
/** Index format version */
|
|
114
|
+
version: string;
|
|
115
|
+
|
|
116
|
+
/** When the index was last updated */
|
|
117
|
+
lastUpdated: string;
|
|
118
|
+
|
|
119
|
+
/** Root directory that was indexed */
|
|
120
|
+
rootDir: string;
|
|
121
|
+
|
|
122
|
+
/** All indexed patterns */
|
|
123
|
+
patterns: PatternEntry[];
|
|
124
|
+
|
|
125
|
+
/** Index statistics */
|
|
126
|
+
stats: PatternIndexStats;
|
|
127
|
+
|
|
128
|
+
/** Files that were indexed */
|
|
129
|
+
files: IndexedFile[];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Statistics about the pattern index.
|
|
134
|
+
*/
|
|
135
|
+
export interface PatternIndexStats {
|
|
136
|
+
totalPatterns: number;
|
|
137
|
+
totalFiles: number;
|
|
138
|
+
byType: Record<PatternType, number>;
|
|
139
|
+
indexDurationMs: number;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Information about an indexed file.
|
|
144
|
+
*/
|
|
145
|
+
export interface IndexedFile {
|
|
146
|
+
path: string;
|
|
147
|
+
hash: string;
|
|
148
|
+
patternCount: number;
|
|
149
|
+
indexedAt: string;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Configuration for the pattern indexer.
|
|
154
|
+
*/
|
|
155
|
+
export interface PatternIndexConfig {
|
|
156
|
+
/** Directories to index (defaults to src/) */
|
|
157
|
+
include: string[];
|
|
158
|
+
|
|
159
|
+
/** Directories to exclude */
|
|
160
|
+
exclude: string[];
|
|
161
|
+
|
|
162
|
+
/** File extensions to index */
|
|
163
|
+
extensions: string[];
|
|
164
|
+
|
|
165
|
+
/** Whether to index test files */
|
|
166
|
+
indexTests: boolean;
|
|
167
|
+
|
|
168
|
+
/** Whether to index node_modules */
|
|
169
|
+
indexNodeModules: boolean;
|
|
170
|
+
|
|
171
|
+
/** Minimum pattern name length to index */
|
|
172
|
+
minNameLength: number;
|
|
173
|
+
|
|
174
|
+
/** Custom categories for patterns */
|
|
175
|
+
categories: Record<string, string[]>;
|
|
176
|
+
|
|
177
|
+
/** Whether to generate semantic embeddings for patterns */
|
|
178
|
+
useEmbeddings?: boolean;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Result from matching against the pattern index.
|
|
183
|
+
*/
|
|
184
|
+
export interface PatternMatchResult {
|
|
185
|
+
/** The query that was matched */
|
|
186
|
+
query: string;
|
|
187
|
+
|
|
188
|
+
/** All matches found */
|
|
189
|
+
matches: PatternMatch[];
|
|
190
|
+
|
|
191
|
+
/** Suggestion for what to do */
|
|
192
|
+
suggestion: string;
|
|
193
|
+
|
|
194
|
+
/** Whether human override is available */
|
|
195
|
+
canOverride: boolean;
|
|
196
|
+
|
|
197
|
+
/** Overall status */
|
|
198
|
+
status: 'FOUND_SIMILAR' | 'NO_MATCH' | 'OVERRIDE_ALLOWED';
|
|
199
|
+
|
|
200
|
+
/** Recommended action */
|
|
201
|
+
action: 'BLOCK' | 'WARN' | 'ALLOW';
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* A single pattern match.
|
|
206
|
+
*/
|
|
207
|
+
export interface PatternMatch {
|
|
208
|
+
/** The matched pattern */
|
|
209
|
+
pattern: PatternEntry;
|
|
210
|
+
|
|
211
|
+
/** How the match was determined */
|
|
212
|
+
matchType: 'exact' | 'fuzzy' | 'signature' | 'semantic';
|
|
213
|
+
|
|
214
|
+
/** Confidence score 0-100 */
|
|
215
|
+
confidence: number;
|
|
216
|
+
|
|
217
|
+
/** Human-readable reason for the match */
|
|
218
|
+
reason: string;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Human override entry.
|
|
223
|
+
*/
|
|
224
|
+
export interface PatternOverride {
|
|
225
|
+
/** Pattern name or glob */
|
|
226
|
+
pattern: string;
|
|
227
|
+
|
|
228
|
+
/** Why the override was granted */
|
|
229
|
+
reason: string;
|
|
230
|
+
|
|
231
|
+
/** When the override expires */
|
|
232
|
+
expiresAt?: string;
|
|
233
|
+
|
|
234
|
+
/** Who approved the override */
|
|
235
|
+
approvedBy?: string;
|
|
236
|
+
|
|
237
|
+
/** When the override was created */
|
|
238
|
+
createdAt: string;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Staleness detection result.
|
|
243
|
+
*/
|
|
244
|
+
export interface StalenessResult {
|
|
245
|
+
/** Overall status */
|
|
246
|
+
status: 'FRESH' | 'STALE' | 'DEPRECATED';
|
|
247
|
+
|
|
248
|
+
/** All staleness issues found */
|
|
249
|
+
issues: StalenessIssue[];
|
|
250
|
+
|
|
251
|
+
/** Project context (versions) */
|
|
252
|
+
projectContext: Record<string, string>;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* A single staleness issue.
|
|
257
|
+
*/
|
|
258
|
+
export interface StalenessIssue {
|
|
259
|
+
/** Line number */
|
|
260
|
+
line: number;
|
|
261
|
+
|
|
262
|
+
/** The stale pattern */
|
|
263
|
+
pattern: string;
|
|
264
|
+
|
|
265
|
+
/** Severity */
|
|
266
|
+
severity: 'error' | 'warning' | 'info';
|
|
267
|
+
|
|
268
|
+
/** Why it's stale */
|
|
269
|
+
reason: string;
|
|
270
|
+
|
|
271
|
+
/** What to use instead */
|
|
272
|
+
replacement: string;
|
|
273
|
+
|
|
274
|
+
/** Link to documentation */
|
|
275
|
+
docs?: string;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Security/CVE entry for a package.
|
|
280
|
+
*/
|
|
281
|
+
export interface SecurityEntry {
|
|
282
|
+
/** CVE Identifier (e.g., CVE-2021-1234) */
|
|
283
|
+
cveId: string;
|
|
284
|
+
|
|
285
|
+
/** Package name */
|
|
286
|
+
packageName: string;
|
|
287
|
+
|
|
288
|
+
/** Vulnerable version range (semver) */
|
|
289
|
+
vulnerableRange: string;
|
|
290
|
+
|
|
291
|
+
/** Severity level */
|
|
292
|
+
severity: 'critical' | 'high' | 'moderate' | 'low';
|
|
293
|
+
|
|
294
|
+
/** Brief description of the vulnerability */
|
|
295
|
+
title: string;
|
|
296
|
+
|
|
297
|
+
/** Link to advisory */
|
|
298
|
+
url: string;
|
|
299
|
+
|
|
300
|
+
/** The version of the package in the current project */
|
|
301
|
+
currentVersion?: string;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Result from security check.
|
|
306
|
+
*/
|
|
307
|
+
export interface SecurityResult {
|
|
308
|
+
/** Overall security status */
|
|
309
|
+
status: 'SECURE' | 'VULNERABLE';
|
|
310
|
+
|
|
311
|
+
/** All CVEs/vulnerabilities found */
|
|
312
|
+
vulnerabilities: SecurityEntry[];
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Deprecation entry in the deprecation database.
|
|
317
|
+
*/
|
|
318
|
+
export interface DeprecationEntry {
|
|
319
|
+
/** Pattern to match (can be regex) */
|
|
320
|
+
pattern: string;
|
|
321
|
+
|
|
322
|
+
/** Library this belongs to */
|
|
323
|
+
library?: string;
|
|
324
|
+
|
|
325
|
+
/** Version when deprecated */
|
|
326
|
+
deprecatedIn: string;
|
|
327
|
+
|
|
328
|
+
/** Suggested replacement */
|
|
329
|
+
replacement: string;
|
|
330
|
+
|
|
331
|
+
/** Severity level */
|
|
332
|
+
severity: 'error' | 'warning' | 'info';
|
|
333
|
+
|
|
334
|
+
/** Additional context */
|
|
335
|
+
reason?: string;
|
|
336
|
+
|
|
337
|
+
/** Documentation link */
|
|
338
|
+
docs?: string;
|
|
339
|
+
}
|
package/vitest.config.ts
ADDED
package/vitest.setup.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
// Mock Transformers.js to avoid native binary dependency issues and speed up tests
|
|
4
|
+
vi.mock('@xenova/transformers', () => ({
|
|
5
|
+
pipeline: async () => {
|
|
6
|
+
// Return a mock extractor that produces deterministic "embeddings"
|
|
7
|
+
return async (text: string) => {
|
|
8
|
+
// Create a fake vector based on the text length or hash
|
|
9
|
+
const vector = new Array(384).fill(0);
|
|
10
|
+
for (let i = 0; i < Math.min(text.length, 384); i++) {
|
|
11
|
+
vector[i] = text.charCodeAt(i) / 255;
|
|
12
|
+
}
|
|
13
|
+
return { data: new Float32Array(vector) };
|
|
14
|
+
};
|
|
15
|
+
},
|
|
16
|
+
env: {
|
|
17
|
+
allowImageProcessors: false,
|
|
18
|
+
},
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
// Also mock sharp just in case something else pulls it in
|
|
22
|
+
vi.mock('sharp', () => ({
|
|
23
|
+
default: () => ({
|
|
24
|
+
resize: () => ({
|
|
25
|
+
toFormat: () => ({
|
|
26
|
+
toBuffer: async () => Buffer.from([]),
|
|
27
|
+
}),
|
|
28
|
+
}),
|
|
29
|
+
}),
|
|
30
|
+
}));
|