@kevinbermudezc/context-guard 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -4
- package/dist/bin/claude-hook.js +19 -4
- package/dist/bin/claude-hook.js.map +1 -1
- package/dist/src/file-classifier.d.ts +15 -0
- package/dist/src/file-classifier.d.ts.map +1 -0
- package/dist/src/file-classifier.js +101 -0
- package/dist/src/file-classifier.js.map +1 -0
- package/dist/src/import-collapser.d.ts +13 -0
- package/dist/src/import-collapser.d.ts.map +1 -0
- package/dist/src/import-collapser.js +112 -0
- package/dist/src/import-collapser.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +26 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/skeletonizer.d.ts +2 -0
- package/dist/src/skeletonizer.d.ts.map +1 -1
- package/dist/src/skeletonizer.js +86 -7
- package/dist/src/skeletonizer.js.map +1 -1
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tests/claude-hook.test.js +56 -10
- package/dist/tests/claude-hook.test.js.map +1 -1
- package/dist/tests/file-classifier.test.d.ts +2 -0
- package/dist/tests/file-classifier.test.d.ts.map +1 -0
- package/dist/tests/file-classifier.test.js +46 -0
- package/dist/tests/file-classifier.test.js.map +1 -0
- package/dist/tests/framework-sfc.test.d.ts +2 -0
- package/dist/tests/framework-sfc.test.d.ts.map +1 -0
- package/dist/tests/framework-sfc.test.js +151 -0
- package/dist/tests/framework-sfc.test.js.map +1 -0
- package/dist/tests/import-collapser.test.d.ts +2 -0
- package/dist/tests/import-collapser.test.d.ts.map +1 -0
- package/dist/tests/import-collapser.test.js +35 -0
- package/dist/tests/import-collapser.test.js.map +1 -0
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -90,16 +90,20 @@ Add ContextGuard to your `.claude/settings.json` (at project root or `~/.claude/
|
|
|
90
90
|
"hooks": {
|
|
91
91
|
"PreToolUse": [
|
|
92
92
|
{
|
|
93
|
-
"matcher": "
|
|
94
|
-
"
|
|
95
|
-
|
|
93
|
+
"matcher": "Read|Bash",
|
|
94
|
+
"hooks": [
|
|
95
|
+
{
|
|
96
|
+
"type": "command",
|
|
97
|
+
"command": "node ./node_modules/@kevinbermudezc/context-guard/dist/bin/claude-hook.js"
|
|
98
|
+
}
|
|
99
|
+
]
|
|
96
100
|
}
|
|
97
101
|
]
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
104
|
```
|
|
101
105
|
|
|
102
|
-
That's it! When Claude Code attempts to run `
|
|
106
|
+
That's it! When Claude Code attempts to run `Read` (or raw bash reads like `cat massive-file.ts`), ContextGuard will intercept it, extract the structural map, and instruct Claude to seek only the exact line range it needs.
|
|
103
107
|
|
|
104
108
|
---
|
|
105
109
|
|
|
@@ -154,6 +158,13 @@ pnpm test
|
|
|
154
158
|
|
|
155
159
|
---
|
|
156
160
|
|
|
161
|
+
## 📚 Documentation & Roadmap
|
|
162
|
+
|
|
163
|
+
* **[Software Design Document (SDD)](docs/SDD.md):** Complete technical architecture, FinOps mathematical breakdown, and threat model.
|
|
164
|
+
* **[Product Roadmap (ROADMAP.md)](ROADMAP.md):** Vision and milestones for Universal MCP Server, native Cursor, Antigravity, Kiro, and Windsurf support.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
157
168
|
## 📄 License
|
|
158
169
|
|
|
159
170
|
MIT © [Kevin Bermudez](https://github.com/kevinbermudezc)
|
package/dist/bin/claude-hook.js
CHANGED
|
@@ -10,6 +10,7 @@ import fs from 'node:fs';
|
|
|
10
10
|
import path from 'node:path';
|
|
11
11
|
import { CONFIG } from '../src/config.js';
|
|
12
12
|
import { extractCodeSkeleton } from '../src/skeletonizer.js';
|
|
13
|
+
import { classifyFile } from '../src/file-classifier.js';
|
|
13
14
|
async function runHook() {
|
|
14
15
|
const inputChunks = [];
|
|
15
16
|
for await (const chunk of process.stdin) {
|
|
@@ -29,9 +30,11 @@ async function runHook() {
|
|
|
29
30
|
const toolInput = payload.tool_input || payload.input || {};
|
|
30
31
|
let targetFilePath = null;
|
|
31
32
|
let isScoped = false;
|
|
32
|
-
// 1. Intercept "View" or
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
// 1. Intercept "Read", "View" or other file reading tools in Claude Code
|
|
34
|
+
const isReadTool = ['Read', 'View', 'view_file', 'readFile', 'read_file'].includes(toolName || '');
|
|
35
|
+
if (isReadTool) {
|
|
36
|
+
const rawPath = toolInput.file_path || toolInput.path || toolInput.filePath || toolInput.AbsolutePath;
|
|
37
|
+
targetFilePath = typeof rawPath === 'string' ? rawPath : null;
|
|
35
38
|
// Check if Claude specified line bounds
|
|
36
39
|
if (toolInput.offset !== undefined ||
|
|
37
40
|
toolInput.limit !== undefined ||
|
|
@@ -60,6 +63,18 @@ async function runHook() {
|
|
|
60
63
|
if (!fs.existsSync(resolvedPath) || fs.statSync(resolvedPath).isDirectory()) {
|
|
61
64
|
process.exit(0);
|
|
62
65
|
}
|
|
66
|
+
// Check for Binaries, Lockfiles, and Minified files
|
|
67
|
+
const classification = classifyFile(resolvedPath);
|
|
68
|
+
if (classification.category !== 'source_code') {
|
|
69
|
+
const feedback = [
|
|
70
|
+
`🛑 [CONTEXTGUARD: ACCESO DENEGADO - ${classification.category.toUpperCase()}]`,
|
|
71
|
+
classification.reason,
|
|
72
|
+
``,
|
|
73
|
+
`👉 ${classification.recommendedAction}`
|
|
74
|
+
].join('\n');
|
|
75
|
+
process.stderr.write(feedback + '\n');
|
|
76
|
+
process.exit(2);
|
|
77
|
+
}
|
|
63
78
|
const stat = fs.statSync(resolvedPath);
|
|
64
79
|
const rawContent = fs.readFileSync(resolvedPath, 'utf-8');
|
|
65
80
|
const lines = rawContent.split('\n');
|
|
@@ -85,7 +100,7 @@ async function runHook() {
|
|
|
85
100
|
`--------------------------------------------------------------------------------`,
|
|
86
101
|
``,
|
|
87
102
|
`🎯 ACCIÓN RECOMENDADA:`,
|
|
88
|
-
`Revisa las firmas anteriores y ejecuta la herramienta "View" especificando los parámetros "offset" y "limit"
|
|
103
|
+
`Revisa las firmas anteriores y ejecuta la herramienta "Read" (o "View") especificando los parámetros "offset" y "limit" para inspeccionar únicamente la sección necesaria.`
|
|
89
104
|
].join('\n');
|
|
90
105
|
// Emit to stderr and exit with code 2 to trigger a controlled block with system feedback in Claude Code
|
|
91
106
|
process.stderr.write(feedbackMessage + '\n');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-hook.js","sourceRoot":"","sources":["../../bin/claude-hook.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-hook.js","sourceRoot":"","sources":["../../bin/claude-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type FileCategory = 'binary' | 'lockfile' | 'minified' | 'source_code';
|
|
2
|
+
export interface FileClassification {
|
|
3
|
+
category: FileCategory;
|
|
4
|
+
reason?: string;
|
|
5
|
+
recommendedAction?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Inspects magic bytes (first 512 bytes) to detect binary contents
|
|
9
|
+
*/
|
|
10
|
+
export declare function isBinaryBuffer(buffer: Buffer): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Classifies a file to determine if it should be shunted, blocked, or parsed
|
|
13
|
+
*/
|
|
14
|
+
export declare function classifyFile(filePath: string): FileClassification;
|
|
15
|
+
//# sourceMappingURL=file-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-classifier.d.ts","sourceRoot":"","sources":["../../src/file-classifier.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,aAAa,CAAC;AAE9E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AA0BD;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAmBtD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAuDjE"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
const BINARY_EXTENSIONS = new Set([
|
|
4
|
+
// Images
|
|
5
|
+
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.bmp', '.tiff', '.avif',
|
|
6
|
+
// Documents & Media
|
|
7
|
+
'.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.mp3', '.mp4', '.mov', '.avi',
|
|
8
|
+
// Fonts & Binaries
|
|
9
|
+
'.woff', '.woff2', '.ttf', '.otf', '.eot',
|
|
10
|
+
'.wasm', '.dylib', '.so', '.dll', '.exe', '.bin', '.obj', '.o',
|
|
11
|
+
// Archives & Databases
|
|
12
|
+
'.zip', '.tar', '.gz', '.7z', '.rar', '.bz2', '.sqlite', '.sqlite3', '.db'
|
|
13
|
+
]);
|
|
14
|
+
const LOCKFILES = new Set([
|
|
15
|
+
'pnpm-lock.yaml',
|
|
16
|
+
'package-lock.json',
|
|
17
|
+
'yarn.lock',
|
|
18
|
+
'cargo.lock',
|
|
19
|
+
'composer.lock',
|
|
20
|
+
'gemfile.lock',
|
|
21
|
+
'poetry.lock',
|
|
22
|
+
'bun.lockb',
|
|
23
|
+
'bun.lock'
|
|
24
|
+
]);
|
|
25
|
+
/**
|
|
26
|
+
* Inspects magic bytes (first 512 bytes) to detect binary contents
|
|
27
|
+
*/
|
|
28
|
+
export function isBinaryBuffer(buffer) {
|
|
29
|
+
const checkLen = Math.min(buffer.length, 512);
|
|
30
|
+
if (checkLen === 0)
|
|
31
|
+
return false;
|
|
32
|
+
let nonPrintableCount = 0;
|
|
33
|
+
for (let i = 0; i < checkLen; i++) {
|
|
34
|
+
const byte = buffer[i];
|
|
35
|
+
// Check for null bytes (typical of binary data)
|
|
36
|
+
if (byte === 0) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
// Byte values below 32 (except common whitespace: \t, \n, \r) or above 126
|
|
40
|
+
if ((byte < 7 || (byte > 13 && byte < 32)) && byte !== 27) {
|
|
41
|
+
nonPrintableCount++;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// If > 25% of bytes are non-printable control characters, consider it binary
|
|
45
|
+
return nonPrintableCount / checkLen > 0.25;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Classifies a file to determine if it should be shunted, blocked, or parsed
|
|
49
|
+
*/
|
|
50
|
+
export function classifyFile(filePath) {
|
|
51
|
+
const fileName = path.basename(filePath).toLowerCase();
|
|
52
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
53
|
+
// 1. Check for Lockfiles
|
|
54
|
+
if (LOCKFILES.has(fileName)) {
|
|
55
|
+
return {
|
|
56
|
+
category: 'lockfile',
|
|
57
|
+
reason: `El archivo "${path.basename(filePath)}" es un lockfile de dependencias.`,
|
|
58
|
+
recommendedAction: `No leas el lockfile crudo. Usa comandos de introspección como "pnpm why <paquete>" o "npm ls <paquete>".`
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// 2. Check for Minified / Sourcemaps
|
|
62
|
+
if (fileName.endsWith('.min.js') || fileName.endsWith('.min.css') || fileName.endsWith('.bundle.js') || fileName.endsWith('.map')) {
|
|
63
|
+
return {
|
|
64
|
+
category: 'minified',
|
|
65
|
+
reason: `El archivo "${path.basename(filePath)}" está minificado o es un sourcemap.`,
|
|
66
|
+
recommendedAction: `Inspecciona los archivos originales de código fuente en "src/" en lugar del bundle empaquetado.`
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// 3. Check for Binary Extensions
|
|
70
|
+
if (BINARY_EXTENSIONS.has(ext)) {
|
|
71
|
+
const isDoc = ext === '.pdf' || ext.startsWith('.doc') || ext.startsWith('.xls');
|
|
72
|
+
return {
|
|
73
|
+
category: 'binary',
|
|
74
|
+
reason: `El archivo "${path.basename(filePath)}" es un recurso binario (${ext}).`,
|
|
75
|
+
recommendedAction: isDoc
|
|
76
|
+
? `Usa herramientas como "pdftotext" o lectores de documentos para extraer texto plano.`
|
|
77
|
+
: `Los archivos multimedia y binarios no deben volcarse como texto. Usa herramientas de visión multimodal o comandos de sistema.`
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// 4. Inspect buffer if file exists
|
|
81
|
+
try {
|
|
82
|
+
const fd = fs.openSync(filePath, 'r');
|
|
83
|
+
const buffer = Buffer.alloc(512);
|
|
84
|
+
const bytesRead = fs.readSync(fd, buffer, 0, 512, 0);
|
|
85
|
+
fs.closeSync(fd);
|
|
86
|
+
if (isBinaryBuffer(buffer.subarray(0, bytesRead))) {
|
|
87
|
+
return {
|
|
88
|
+
category: 'binary',
|
|
89
|
+
reason: `El archivo "${path.basename(filePath)}" contiene bytes binarios o caracteres nulos.`,
|
|
90
|
+
recommendedAction: `No intentes leer archivos binarios como texto plano.`
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// If unable to open or read header, proceed with fallback
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
category: 'source_code'
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=file-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-classifier.js","sourceRoot":"","sources":["../../src/file-classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface CollapsedImportResult {
|
|
2
|
+
hasCollapsed: boolean;
|
|
3
|
+
lines: string[];
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Checks if a line is an import statement
|
|
7
|
+
*/
|
|
8
|
+
export declare function isImportLine(line: string, ext: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Processes a collection of lines, collapsing import walls exceeding threshold
|
|
11
|
+
*/
|
|
12
|
+
export declare function collapseImportWall(rawLines: string[], ext: string, maxThreshold?: number): CollapsedImportResult;
|
|
13
|
+
//# sourceMappingURL=import-collapser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-collapser.d.ts","sourceRoot":"","sources":["../../src/import-collapser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AA0CD;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAiB/D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,GAAE,MAAU,GAAG,qBAAqB,CAkEnH"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses import source from JS/TS and Python statements
|
|
3
|
+
*/
|
|
4
|
+
function extractImportSource(line) {
|
|
5
|
+
const trimmed = line.trim();
|
|
6
|
+
// TypeScript / JavaScript: import ... from 'source' or import 'source'
|
|
7
|
+
const tsMatch = trimmed.match(/from\s+['"]([^'"]+)['"]/);
|
|
8
|
+
if (tsMatch) {
|
|
9
|
+
const src = tsMatch[1];
|
|
10
|
+
return { source: src, isExternal: !src.startsWith('.') };
|
|
11
|
+
}
|
|
12
|
+
const tsBareMatch = trimmed.match(/^import\s+['"]([^'"]+)['"]/);
|
|
13
|
+
if (tsBareMatch) {
|
|
14
|
+
const src = tsBareMatch[1];
|
|
15
|
+
return { source: src, isExternal: !src.startsWith('.') };
|
|
16
|
+
}
|
|
17
|
+
// Python: from module import ... or import module
|
|
18
|
+
const pyFromMatch = trimmed.match(/^from\s+([A-Za-z0-9_.]+)\s+import/);
|
|
19
|
+
if (pyFromMatch) {
|
|
20
|
+
const src = pyFromMatch[1];
|
|
21
|
+
return { source: src, isExternal: !src.startsWith('.') };
|
|
22
|
+
}
|
|
23
|
+
const pyImportMatch = trimmed.match(/^import\s+([A-Za-z0-9_.]+)/);
|
|
24
|
+
if (pyImportMatch) {
|
|
25
|
+
const src = pyImportMatch[1];
|
|
26
|
+
return { source: src, isExternal: !src.startsWith('.') };
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Checks if a line is an import statement
|
|
32
|
+
*/
|
|
33
|
+
export function isImportLine(line, ext) {
|
|
34
|
+
const trimmed = line.trim();
|
|
35
|
+
const normalized = ext.toLowerCase().replace(/^\./, '');
|
|
36
|
+
if (['ts', 'tsx', 'js', 'jsx', 'mjs', 'cjs', 'svelte', 'vue', 'astro'].includes(normalized)) {
|
|
37
|
+
return trimmed.startsWith('import ') || trimmed.startsWith('import{') || /^const\s+.*\s*=\s*require\(/.test(trimmed);
|
|
38
|
+
}
|
|
39
|
+
if (normalized === 'py') {
|
|
40
|
+
return trimmed.startsWith('import ') || trimmed.startsWith('from ');
|
|
41
|
+
}
|
|
42
|
+
if (normalized === 'go') {
|
|
43
|
+
return trimmed.startsWith('import ') || trimmed.startsWith('import (');
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Processes a collection of lines, collapsing import walls exceeding threshold
|
|
49
|
+
*/
|
|
50
|
+
export function collapseImportWall(rawLines, ext, maxThreshold = 5) {
|
|
51
|
+
const imports = [];
|
|
52
|
+
const otherLines = [];
|
|
53
|
+
rawLines.forEach((line, index) => {
|
|
54
|
+
const lineNum = index + 1;
|
|
55
|
+
if (isImportLine(line, ext)) {
|
|
56
|
+
const parsed = extractImportSource(line) || { source: '', isExternal: true };
|
|
57
|
+
imports.push({
|
|
58
|
+
lineNum,
|
|
59
|
+
rawText: line.trim(),
|
|
60
|
+
source: parsed.source,
|
|
61
|
+
isExternal: parsed.isExternal
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
otherLines.push({ lineNum, text: line });
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
// If imports are below or equal to threshold, keep them intact
|
|
69
|
+
if (imports.length <= maxThreshold) {
|
|
70
|
+
return {
|
|
71
|
+
hasCollapsed: false,
|
|
72
|
+
lines: rawLines
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// Extract unique external and local package names
|
|
76
|
+
const externalPkgs = new Set();
|
|
77
|
+
const localModules = new Set();
|
|
78
|
+
imports.forEach((imp) => {
|
|
79
|
+
if (!imp.source)
|
|
80
|
+
return;
|
|
81
|
+
if (imp.isExternal) {
|
|
82
|
+
// For scoped packages like @angular/core, grab full package name
|
|
83
|
+
const parts = imp.source.split('/');
|
|
84
|
+
const pkg = imp.source.startsWith('@') ? `${parts[0]}/${parts[1] || ''}` : parts[0];
|
|
85
|
+
externalPkgs.add(pkg);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const parts = imp.source.split('/');
|
|
89
|
+
const mod = parts.slice(0, 2).join('/');
|
|
90
|
+
localModules.add(mod);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
const startLine = imports[0].lineNum;
|
|
94
|
+
const endLine = imports[imports.length - 1].lineNum;
|
|
95
|
+
const extList = Array.from(externalPkgs).slice(0, 4).join(', ');
|
|
96
|
+
const locList = Array.from(localModules).slice(0, 3).join(', ');
|
|
97
|
+
const summaryParts = [];
|
|
98
|
+
if (extList)
|
|
99
|
+
summaryParts.push(`Dependencias: ${extList}${externalPkgs.size > 4 ? '...' : ''}`);
|
|
100
|
+
if (locList)
|
|
101
|
+
summaryParts.push(`Locales: ${locList}${localModules.size > 3 ? '...' : ''}`);
|
|
102
|
+
const details = summaryParts.length > 0 ? ` (${summaryParts.join(' | ')})` : '';
|
|
103
|
+
const collapsedBanner = [
|
|
104
|
+
`[L${startLine}-L${endLine}] 📦 ${imports.length} imports colapsados${details}`,
|
|
105
|
+
`👉 Tip: Si necesitas ver todas las dependencias, corre Read(offset=${startLine}, limit=${endLine - startLine + 1})`
|
|
106
|
+
].join('\n');
|
|
107
|
+
return {
|
|
108
|
+
hasCollapsed: true,
|
|
109
|
+
lines: [collapsedBanner]
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=import-collapser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-collapser.js","sourceRoot":"","sources":["../../src/import-collapser.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export * from './types.js';
|
|
|
3
3
|
export * from './config.js';
|
|
4
4
|
export * from './skeletonizer.js';
|
|
5
5
|
export * from './worker-model.js';
|
|
6
|
+
export * from './file-classifier.js';
|
|
7
|
+
export * from './import-collapser.js';
|
|
6
8
|
/**
|
|
7
9
|
* Main engine of ContextGuard
|
|
8
10
|
* Evaluates file size and either passes it through or shunts it to an AST/Worker summary.
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAExE,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AAEtC;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA4HrG"}
|
package/dist/src/index.js
CHANGED
|
@@ -3,10 +3,13 @@ import path from 'node:path';
|
|
|
3
3
|
import { CONFIG } from './config.js';
|
|
4
4
|
import { extractCodeSkeleton } from './skeletonizer.js';
|
|
5
5
|
import { callWorkerModel } from './worker-model.js';
|
|
6
|
+
import { classifyFile } from './file-classifier.js';
|
|
6
7
|
export * from './types.js';
|
|
7
8
|
export * from './config.js';
|
|
8
9
|
export * from './skeletonizer.js';
|
|
9
10
|
export * from './worker-model.js';
|
|
11
|
+
export * from './file-classifier.js';
|
|
12
|
+
export * from './import-collapser.js';
|
|
10
13
|
/**
|
|
11
14
|
* Main engine of ContextGuard
|
|
12
15
|
* Evaluates file size and either passes it through or shunts it to an AST/Worker summary.
|
|
@@ -21,6 +24,29 @@ export async function processWithContextGuard(options) {
|
|
|
21
24
|
content: ''
|
|
22
25
|
};
|
|
23
26
|
}
|
|
27
|
+
// 1. Check for Binaries, Lockfiles, and Minified files
|
|
28
|
+
const classification = classifyFile(resolved);
|
|
29
|
+
if (classification.category === 'binary') {
|
|
30
|
+
return {
|
|
31
|
+
status: 'BLOCKED_BINARY',
|
|
32
|
+
reason: classification.reason,
|
|
33
|
+
content: `<!-- CONTEXTGUARD: ${classification.reason} -->\n<!-- ${classification.recommendedAction} -->`
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (classification.category === 'lockfile') {
|
|
37
|
+
return {
|
|
38
|
+
status: 'BLOCKED_LOCKFILE',
|
|
39
|
+
reason: classification.reason,
|
|
40
|
+
content: `<!-- CONTEXTGUARD: ${classification.reason} -->\n<!-- ${classification.recommendedAction} -->`
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (classification.category === 'minified') {
|
|
44
|
+
return {
|
|
45
|
+
status: 'BLOCKED_MINIFIED',
|
|
46
|
+
reason: classification.reason,
|
|
47
|
+
content: `<!-- CONTEXTGUARD: ${classification.reason} -->\n<!-- ${classification.recommendedAction} -->`
|
|
48
|
+
};
|
|
49
|
+
}
|
|
24
50
|
const stat = fs.statSync(resolved);
|
|
25
51
|
const rawContent = fs.readFileSync(resolved, 'utf-8');
|
|
26
52
|
const lines = rawContent.split('\n');
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tier 0 Structural Skeletonizer
|
|
3
3
|
* Extracts structural declarations, signatures, imports, and types with line numbers.
|
|
4
|
+
* Supports TypeScript, JavaScript, Python, Go, Rust, Java, C#, and
|
|
5
|
+
* Frontend Single File Components (Svelte, Vue, Angular, Astro).
|
|
4
6
|
* Cost: $0.00 | Execution: < 5ms
|
|
5
7
|
*/
|
|
6
8
|
export declare function isSupportedExtension(ext: string): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skeletonizer.d.ts","sourceRoot":"","sources":["../../src/skeletonizer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"skeletonizer.d.ts","sourceRoot":"","sources":["../../src/skeletonizer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA8DH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa/D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoF/E"}
|
package/dist/src/skeletonizer.js
CHANGED
|
@@ -1,15 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tier 0 Structural Skeletonizer
|
|
3
3
|
* Extracts structural declarations, signatures, imports, and types with line numbers.
|
|
4
|
+
* Supports TypeScript, JavaScript, Python, Go, Rust, Java, C#, and
|
|
5
|
+
* Frontend Single File Components (Svelte, Vue, Angular, Astro).
|
|
4
6
|
* Cost: $0.00 | Execution: < 5ms
|
|
5
7
|
*/
|
|
8
|
+
import { isImportLine, collapseImportWall } from './import-collapser.js';
|
|
6
9
|
const LANGUAGE_PATTERNS = {
|
|
7
|
-
// TypeScript &
|
|
10
|
+
// TypeScript, JavaScript & Angular
|
|
8
11
|
ts: [
|
|
9
12
|
/^(export\s+)?(default\s+)?(class|interface|type|enum)\s+([A-Za-z0-9_]+)/,
|
|
10
13
|
/^(export\s+)?(async\s+)?function\s+([A-Za-z0-9_]+)\s*\(/,
|
|
11
14
|
/^(export\s+)?const\s+([A-Za-z0-9_]+)\s*=\s*(async\s*)?\(/,
|
|
12
|
-
/^(export\s+)?((public|private|protected|static|async|\*)\s+)*([A-Za-z0-9_]+)\s*\([^)]*\)\s*[:{]
|
|
15
|
+
/^(export\s+)?((public|private|protected|static|async|readonly|\*)\s+)*([A-Za-z0-9_]+)\s*\([^)]*\)\s*[:{]/,
|
|
16
|
+
// Angular Decorators & Signals
|
|
17
|
+
/^@(Component|Injectable|Directive|Pipe|NgModule)\s*\(/,
|
|
18
|
+
/^@(Input|Output)\s*\(\s*\)\s+([A-Za-z0-9_]+)/,
|
|
19
|
+
/^(public|private|protected|readonly|\s+)*(readonly\s+)?([A-Za-z0-9_]+)\s*=\s*(input|output|model|computed|signal)(\.[A-Za-z0-9_]+)?\s*[\(<]/,
|
|
20
|
+
/^(ngOnInit|ngOnChanges|ngOnDestroy|ngAfterViewInit)\s*\(/
|
|
21
|
+
],
|
|
22
|
+
// Svelte Component Logic
|
|
23
|
+
svelte: [
|
|
24
|
+
/^(export\s+)?let\s+([A-Za-z0-9_]+)/,
|
|
25
|
+
/^(let|const)\s+([A-Za-z0-9_{}\s,]+)\s*=\s*\$(props|state|derived|effect)\s*\(/,
|
|
26
|
+
/^\$:\s+/,
|
|
27
|
+
/^(export\s+)?(async\s+)?function\s+([A-Za-z0-9_]+)\s*\(/,
|
|
28
|
+
/^(export\s+)?const\s+([A-Za-z0-9_]+)\s*=\s*(async\s*)?\(/
|
|
29
|
+
],
|
|
30
|
+
// Vue Component Logic
|
|
31
|
+
vue: [
|
|
32
|
+
/^(const|let)\s+([A-Za-z0-9_{}\s,]+)\s*=\s*(defineProps|defineEmits|defineModel)\s*[\(<]/,
|
|
33
|
+
/^(const|let)\s+([A-Za-z0-9_]+)\s*=\s*(ref|computed|reactive)\s*[\(<]/,
|
|
34
|
+
/^(export\s+)?(async\s+)?function\s+([A-Za-z0-9_]+)\s*\(/,
|
|
35
|
+
/^(export\s+)?const\s+([A-Za-z0-9_]+)\s*=\s*(async\s*)?\(/
|
|
36
|
+
],
|
|
37
|
+
// Astro Component Frontmatter
|
|
38
|
+
astro: [
|
|
39
|
+
/^(export\s+)?interface\s+Props/,
|
|
40
|
+
/^(const|let)\s+([A-Za-z0-9_{}\s,]+)\s*=\s*Astro\.props/,
|
|
41
|
+
/^(export\s+)?(async\s+)?function\s+([A-Za-z0-9_]+)\s*\(/,
|
|
42
|
+
/^(export\s+)?const\s+([A-Za-z0-9_]+)\s*=\s*(async\s*)?\(/
|
|
13
43
|
],
|
|
14
44
|
// Python
|
|
15
45
|
py: [
|
|
@@ -37,6 +67,9 @@ export function isSupportedExtension(ext) {
|
|
|
37
67
|
const normalized = ext.toLowerCase().replace(/^\./, '');
|
|
38
68
|
const mapping = {
|
|
39
69
|
ts: 'ts', tsx: 'ts', js: 'ts', jsx: 'ts', mjs: 'ts', cjs: 'ts',
|
|
70
|
+
svelte: 'svelte',
|
|
71
|
+
vue: 'vue',
|
|
72
|
+
astro: 'astro',
|
|
40
73
|
py: 'py',
|
|
41
74
|
go: 'go',
|
|
42
75
|
rs: 'rs',
|
|
@@ -51,26 +84,72 @@ export function extractCodeSkeleton(content, ext) {
|
|
|
51
84
|
const patterns = LANGUAGE_PATTERNS[langKey] || [];
|
|
52
85
|
const lines = content.split('\n');
|
|
53
86
|
const skeleton = [];
|
|
87
|
+
// Separate import lines and scan for style blocks
|
|
88
|
+
const importLines = [];
|
|
89
|
+
const bodyItems = [];
|
|
90
|
+
let insideStyleBlock = false;
|
|
91
|
+
let styleStartLine = 0;
|
|
92
|
+
let styleLineCount = 0;
|
|
54
93
|
lines.forEach((line, index) => {
|
|
55
94
|
const lineNum = index + 1;
|
|
56
95
|
const trimmed = line.trim();
|
|
96
|
+
// 1. Detect and collapse <style> blocks (Svelte / Vue)
|
|
97
|
+
if (trimmed.startsWith('<style') && !insideStyleBlock) {
|
|
98
|
+
insideStyleBlock = true;
|
|
99
|
+
styleStartLine = lineNum;
|
|
100
|
+
styleLineCount = 1;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (insideStyleBlock) {
|
|
104
|
+
styleLineCount++;
|
|
105
|
+
if (trimmed.includes('</style>')) {
|
|
106
|
+
insideStyleBlock = false;
|
|
107
|
+
const styleEndLine = lineNum;
|
|
108
|
+
if (styleLineCount > 5) {
|
|
109
|
+
bodyItems.push({
|
|
110
|
+
lineNum: styleStartLine,
|
|
111
|
+
text: `[L${styleStartLine}-L${styleEndLine}] 🎨 ${styleLineCount} líneas de CSS colapsadas. Corre Read(offset=${styleStartLine}, limit=${styleLineCount}) si necesitas estilos.`
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
57
117
|
if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('#') || trimmed.startsWith('/*')) {
|
|
58
118
|
return;
|
|
59
119
|
}
|
|
60
|
-
//
|
|
61
|
-
if (
|
|
62
|
-
|
|
120
|
+
// 2. Check for imports
|
|
121
|
+
if (isImportLine(line, ext)) {
|
|
122
|
+
importLines.push(line);
|
|
63
123
|
return;
|
|
64
124
|
}
|
|
125
|
+
// 3. Match Structural Patterns
|
|
65
126
|
for (const pattern of patterns) {
|
|
66
127
|
if (pattern.test(trimmed)) {
|
|
67
|
-
// Strip trailing curly braces or semicolons for brevity
|
|
68
128
|
const clean = trimmed.replace(/\{\s*$/, '').trim();
|
|
69
|
-
|
|
129
|
+
bodyItems.push({ lineNum, text: `[L${lineNum}] ${clean}` });
|
|
70
130
|
break;
|
|
71
131
|
}
|
|
72
132
|
}
|
|
73
133
|
});
|
|
134
|
+
// 4. Process and collapse import statements
|
|
135
|
+
if (importLines.length > 0) {
|
|
136
|
+
const collapsed = collapseImportWall(importLines, ext, 5);
|
|
137
|
+
if (collapsed.hasCollapsed) {
|
|
138
|
+
skeleton.push(collapsed.lines[0]);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// If <= 5 imports, keep them as individual lines
|
|
142
|
+
importLines.forEach((impLine) => {
|
|
143
|
+
const originalIndex = lines.findIndex((l) => l.trim() === impLine.trim());
|
|
144
|
+
const lNum = originalIndex !== -1 ? originalIndex + 1 : 1;
|
|
145
|
+
skeleton.push(`[L${lNum}] ${impLine.trim()}`);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// 5. Append body structural declarations
|
|
150
|
+
bodyItems.forEach((item) => {
|
|
151
|
+
skeleton.push(item.text);
|
|
152
|
+
});
|
|
74
153
|
return skeleton.length > 0 ? skeleton.join('\n') : null;
|
|
75
154
|
}
|
|
76
155
|
//# sourceMappingURL=skeletonizer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skeletonizer.js","sourceRoot":"","sources":["../../src/skeletonizer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"skeletonizer.js","sourceRoot":"","sources":["../../src/skeletonizer.ts"],"names":[],"mappings":"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"}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export interface ProcessFileOptions {
|
|
|
18
18
|
endLine?: number;
|
|
19
19
|
forceWorker?: boolean;
|
|
20
20
|
}
|
|
21
|
-
export type ProcessFileStatus = 'PASSTHROUGH_FULL' | 'PASSTHROUGH_SLICE' | 'SHUNTED_LOCAL_AST' | 'SHUNTED_WORKER_MODEL' | 'SHUNT_FALLBACK' | 'ERROR';
|
|
21
|
+
export type ProcessFileStatus = 'PASSTHROUGH_FULL' | 'PASSTHROUGH_SLICE' | 'SHUNTED_LOCAL_AST' | 'SHUNTED_WORKER_MODEL' | 'SHUNT_FALLBACK' | 'BLOCKED_BINARY' | 'BLOCKED_LOCKFILE' | 'BLOCKED_MINIFIED' | 'ERROR';
|
|
22
22
|
export interface ProcessFileResult {
|
|
23
23
|
status: ProcessFileStatus;
|
|
24
24
|
content: string;
|
package/dist/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,iBAAiB,GACzB,kBAAkB,GAClB,mBAAmB,GACnB,mBAAmB,GACnB,sBAAsB,GACtB,gBAAgB,GAChB,OAAO,CAAC;AAEZ,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,iBAAiB,GACzB,kBAAkB,GAClB,mBAAmB,GACnB,mBAAmB,GACnB,sBAAsB,GACtB,gBAAgB,GAChB,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,GAClB,OAAO,CAAC;AAEZ,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB"}
|
|
@@ -22,7 +22,7 @@ function runHookWithStdin(payload) {
|
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
24
|
describe('Claude Code Hook PreToolUse End-to-End', () => {
|
|
25
|
-
it('should block un-scoped
|
|
25
|
+
it('should block un-scoped Read of a file over threshold with Exit Code 2', async () => {
|
|
26
26
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-hook-'));
|
|
27
27
|
const tempFile = path.join(tempDir, 'huge.ts');
|
|
28
28
|
// Create 150 lines of code
|
|
@@ -34,20 +34,20 @@ describe('Claude Code Hook PreToolUse End-to-End', () => {
|
|
|
34
34
|
lines.push('}');
|
|
35
35
|
fs.writeFileSync(tempFile, lines.join('\n'));
|
|
36
36
|
const res = await runHookWithStdin({
|
|
37
|
-
tool_name: '
|
|
37
|
+
tool_name: 'Read',
|
|
38
38
|
tool_input: { file_path: tempFile }
|
|
39
39
|
});
|
|
40
|
-
assert.strictEqual(res.exitCode, 2, 'Must exit with 2 to hard block Claude Code');
|
|
40
|
+
assert.strictEqual(res.exitCode, 2, 'Must exit with 2 to hard block Claude Code on Read');
|
|
41
41
|
assert.ok(res.stderr.includes('CONTEXTGUARD: LECTURA REGULADA'), 'Must emit warning in stderr');
|
|
42
42
|
assert.ok(res.stderr.includes('OrderService'), 'Must include skeleton in stderr');
|
|
43
43
|
fs.rmSync(tempDir, { recursive: true });
|
|
44
44
|
});
|
|
45
|
-
it('should allow (exit 0) when
|
|
45
|
+
it('should allow (exit 0) when Read has offset and limit', async () => {
|
|
46
46
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-hook-'));
|
|
47
47
|
const tempFile = path.join(tempDir, 'huge.ts');
|
|
48
48
|
fs.writeFileSync(tempFile, Array.from({ length: 200 }, () => 'code').join('\n'));
|
|
49
49
|
const res = await runHookWithStdin({
|
|
50
|
-
tool_name: '
|
|
50
|
+
tool_name: 'Read',
|
|
51
51
|
tool_input: {
|
|
52
52
|
file_path: tempFile,
|
|
53
53
|
offset: 10,
|
|
@@ -58,18 +58,64 @@ describe('Claude Code Hook PreToolUse End-to-End', () => {
|
|
|
58
58
|
assert.strictEqual(res.stderr, '');
|
|
59
59
|
fs.rmSync(tempDir, { recursive: true });
|
|
60
60
|
});
|
|
61
|
-
it('should block
|
|
61
|
+
it('should block un-scoped View of a file over threshold with Exit Code 2', async () => {
|
|
62
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-hook-'));
|
|
63
|
+
const tempFile = path.join(tempDir, 'huge.ts');
|
|
64
|
+
// Create 150 lines of code
|
|
65
|
+
const lines = ['export class OrderService {'];
|
|
66
|
+
for (let i = 0; i < 150; i++) {
|
|
67
|
+
lines.push(` // dummy line ${i}`);
|
|
68
|
+
}
|
|
69
|
+
lines.push(' public pay() { return true; }');
|
|
70
|
+
lines.push('}');
|
|
71
|
+
fs.writeFileSync(tempFile, lines.join('\n'));
|
|
72
|
+
const res = await runHookWithStdin({
|
|
73
|
+
tool_name: 'View',
|
|
74
|
+
tool_input: { file_path: tempFile }
|
|
75
|
+
});
|
|
76
|
+
assert.strictEqual(res.exitCode, 2, 'Must exit with 2 to hard block Claude Code on View');
|
|
77
|
+
assert.ok(res.stderr.includes('CONTEXTGUARD: LECTURA REGULADA'), 'Must emit warning in stderr');
|
|
78
|
+
assert.ok(res.stderr.includes('OrderService'), 'Must include skeleton in stderr');
|
|
79
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
80
|
+
});
|
|
81
|
+
it('should allow (exit 0) when View has offset and limit', async () => {
|
|
62
82
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-hook-'));
|
|
63
83
|
const tempFile = path.join(tempDir, 'huge.ts');
|
|
64
84
|
fs.writeFileSync(tempFile, Array.from({ length: 200 }, () => 'code').join('\n'));
|
|
65
85
|
const res = await runHookWithStdin({
|
|
66
|
-
tool_name: '
|
|
86
|
+
tool_name: 'View',
|
|
67
87
|
tool_input: {
|
|
68
|
-
|
|
88
|
+
file_path: tempFile,
|
|
89
|
+
offset: 10,
|
|
90
|
+
limit: 20
|
|
69
91
|
}
|
|
70
92
|
});
|
|
71
|
-
assert.strictEqual(res.exitCode,
|
|
72
|
-
assert.
|
|
93
|
+
assert.strictEqual(res.exitCode, 0, 'Must exit with 0 to allow Claude Code execution');
|
|
94
|
+
assert.strictEqual(res.stderr, '');
|
|
95
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
96
|
+
});
|
|
97
|
+
it('should block reading binary files like images and PDFs with Exit Code 2', async () => {
|
|
98
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-hook-'));
|
|
99
|
+
const imgFile = path.join(tempDir, 'diagram.png');
|
|
100
|
+
fs.writeFileSync(imgFile, Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x00]));
|
|
101
|
+
const res = await runHookWithStdin({
|
|
102
|
+
tool_name: 'Read',
|
|
103
|
+
tool_input: { file_path: imgFile }
|
|
104
|
+
});
|
|
105
|
+
assert.strictEqual(res.exitCode, 2, 'Must block binary file with exit code 2');
|
|
106
|
+
assert.ok(res.stderr.includes('ACCESO DENEGADO - BINARY'), 'Must emit binary warning');
|
|
107
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
108
|
+
});
|
|
109
|
+
it('should block reading lockfiles with Exit Code 2 and suggest CLI introspection', async () => {
|
|
110
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-hook-'));
|
|
111
|
+
const lockFile = path.join(tempDir, 'pnpm-lock.yaml');
|
|
112
|
+
fs.writeFileSync(lockFile, 'lockfileVersion: 5.4\npackages:\n foo: 1.0.0');
|
|
113
|
+
const res = await runHookWithStdin({
|
|
114
|
+
tool_name: 'Read',
|
|
115
|
+
tool_input: { file_path: lockFile }
|
|
116
|
+
});
|
|
117
|
+
assert.strictEqual(res.exitCode, 2, 'Must block lockfile with exit code 2');
|
|
118
|
+
assert.ok(res.stderr.includes('lockfile de dependencias'), 'Must advise using pnpm why');
|
|
73
119
|
fs.rmSync(tempDir, { recursive: true });
|
|
74
120
|
});
|
|
75
121
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-hook.test.js","sourceRoot":"","sources":["../../tests/claude-hook.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,yBAAyB,CAAC,CAAC;AAEzE,SAAS,gBAAgB,CAAC,OAAgB;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE;YACtC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,uBAAuB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAE3E,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAmB,EAAE,EAAE;YACvC,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAE/C,2BAA2B;QAC3B,MAAM,KAAK,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QAC9C,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAE7C,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC;YACjC,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE;SACpC,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"claude-hook.test.js","sourceRoot":"","sources":["../../tests/claude-hook.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,yBAAyB,CAAC,CAAC;AAEzE,SAAS,gBAAgB,CAAC,OAAgB;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE;YACtC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,uBAAuB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAE3E,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAmB,EAAE,EAAE;YACvC,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAE/C,2BAA2B;QAC3B,MAAM,KAAK,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QAC9C,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAE7C,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC;YACjC,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE;SACpC,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,oDAAoD,CAAC,CAAC;QAC1F,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,gCAAgC,CAAC,EAAE,6BAA6B,CAAC,CAAC;QAChG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,iCAAiC,CAAC,CAAC;QAElF,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC/C,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAEjF,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC;YACjC,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE;gBACV,SAAS,EAAE,QAAQ;gBACnB,MAAM,EAAE,EAAE;gBACV,KAAK,EAAE,EAAE;aACV;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,iDAAiD,CAAC,CAAC;QACvF,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAEnC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAE/C,2BAA2B;QAC3B,MAAM,KAAK,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QAC9C,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAE7C,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC;YACjC,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE;SACpC,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,oDAAoD,CAAC,CAAC;QAC1F,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,gCAAgC,CAAC,EAAE,6BAA6B,CAAC,CAAC;QAChG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,iCAAiC,CAAC,CAAC;QAElF,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC/C,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAEjF,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC;YACjC,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE;gBACV,SAAS,EAAE,QAAQ;gBACnB,MAAM,EAAE,EAAE;gBACV,KAAK,EAAE,EAAE;aACV;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,iDAAiD,CAAC,CAAC;QACvF,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAEnC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;QACnE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAClD,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAEvE,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC;YACjC,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE;SACnC,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,yCAAyC,CAAC,CAAC;QAC/E,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,0BAA0B,CAAC,CAAC;QAEvF,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;QACtD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,+CAA+C,CAAC,CAAC;QAE5E,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC;YACjC,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE;SACpC,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,sCAAsC,CAAC,CAAC;QAC5E,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,4BAA4B,CAAC,CAAC;QAEzF,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-classifier.test.d.ts","sourceRoot":"","sources":["../../tests/file-classifier.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import { classifyFile } from '../src/file-classifier.js';
|
|
7
|
+
describe('File Classifier (SPEC-002)', () => {
|
|
8
|
+
it('should detect binary image files by extension', () => {
|
|
9
|
+
const res = classifyFile('assets/logo.png');
|
|
10
|
+
assert.strictEqual(res.category, 'binary');
|
|
11
|
+
assert.ok(res.reason?.includes('.png'));
|
|
12
|
+
});
|
|
13
|
+
it('should detect PDF documents by extension and advise pdftotext', () => {
|
|
14
|
+
const res = classifyFile('docs/manual.pdf');
|
|
15
|
+
assert.strictEqual(res.category, 'binary');
|
|
16
|
+
assert.ok(res.recommendedAction?.includes('pdftotext'));
|
|
17
|
+
});
|
|
18
|
+
it('should detect lockfiles and suggest CLI commands', () => {
|
|
19
|
+
const pnpmRes = classifyFile('pnpm-lock.yaml');
|
|
20
|
+
assert.strictEqual(pnpmRes.category, 'lockfile');
|
|
21
|
+
assert.ok(pnpmRes.recommendedAction?.includes('pnpm why'));
|
|
22
|
+
const npmRes = classifyFile('package-lock.json');
|
|
23
|
+
assert.strictEqual(npmRes.category, 'lockfile');
|
|
24
|
+
assert.ok(npmRes.recommendedAction?.includes('npm ls'));
|
|
25
|
+
});
|
|
26
|
+
it('should detect minified files and recommend source inspection', () => {
|
|
27
|
+
const res = classifyFile('dist/bundle.min.js');
|
|
28
|
+
assert.strictEqual(res.category, 'minified');
|
|
29
|
+
assert.ok(res.recommendedAction?.includes('src/'));
|
|
30
|
+
});
|
|
31
|
+
it('should detect binary contents with null bytes via buffer scanner', () => {
|
|
32
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-bin-'));
|
|
33
|
+
const tempFile = path.join(tempDir, 'unknown_data');
|
|
34
|
+
// Write buffer with null bytes
|
|
35
|
+
const buf = Buffer.from([0x00, 0x01, 0x02, 0x00, 0x7f, 0x80]);
|
|
36
|
+
fs.writeFileSync(tempFile, buf);
|
|
37
|
+
const res = classifyFile(tempFile);
|
|
38
|
+
assert.strictEqual(res.category, 'binary');
|
|
39
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
40
|
+
});
|
|
41
|
+
it('should classify normal code files as source_code', () => {
|
|
42
|
+
const res = classifyFile('src/index.ts');
|
|
43
|
+
assert.strictEqual(res.category, 'source_code');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=file-classifier.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-classifier.test.js","sourceRoot":"","sources":["../../tests/file-classifier.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework-sfc.test.d.ts","sourceRoot":"","sources":["../../tests/framework-sfc.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { extractCodeSkeleton } from '../src/skeletonizer.js';
|
|
4
|
+
describe('Frontend Frameworks & SFC Distillation (SPEC-002)', () => {
|
|
5
|
+
it('should distill Svelte components, extracting runes and collapsing styles', () => {
|
|
6
|
+
const svelteCode = `
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { onMount } from 'svelte';
|
|
9
|
+
|
|
10
|
+
let { name, age } = $props();
|
|
11
|
+
let count = $state(0);
|
|
12
|
+
let double = $derived(count * 2);
|
|
13
|
+
|
|
14
|
+
function increment() {
|
|
15
|
+
count += 1;
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<main>
|
|
20
|
+
<h1>Hello {name}!</h1>
|
|
21
|
+
<button on:click={increment}>Count: {count}</button>
|
|
22
|
+
</main>
|
|
23
|
+
|
|
24
|
+
<style>
|
|
25
|
+
main {
|
|
26
|
+
text-align: center;
|
|
27
|
+
padding: 1em;
|
|
28
|
+
max-width: 240px;
|
|
29
|
+
margin: 0 auto;
|
|
30
|
+
color: red;
|
|
31
|
+
}
|
|
32
|
+
h1 {
|
|
33
|
+
color: #ff3e00;
|
|
34
|
+
text-transform: uppercase;
|
|
35
|
+
font-size: 4em;
|
|
36
|
+
font-weight: 100;
|
|
37
|
+
}
|
|
38
|
+
</style>
|
|
39
|
+
`.trim();
|
|
40
|
+
const skeleton = extractCodeSkeleton(svelteCode, '.svelte');
|
|
41
|
+
assert.ok(skeleton !== null);
|
|
42
|
+
if (!skeleton)
|
|
43
|
+
throw new Error('Skeleton is null');
|
|
44
|
+
assert.ok(skeleton.includes('$props()'));
|
|
45
|
+
assert.ok(skeleton.includes('$state(0)'));
|
|
46
|
+
assert.ok(skeleton.includes('$derived(count * 2)'));
|
|
47
|
+
assert.ok(skeleton.includes('function increment()'));
|
|
48
|
+
// Style block should be collapsed
|
|
49
|
+
assert.ok(skeleton.includes('🎨') && skeleton.includes('líneas de CSS colapsadas'));
|
|
50
|
+
});
|
|
51
|
+
it('should distill Vue components with script setup macros and collapse scoped styles', () => {
|
|
52
|
+
const vueCode = `
|
|
53
|
+
<script setup lang="ts">
|
|
54
|
+
import { ref, computed } from 'vue';
|
|
55
|
+
|
|
56
|
+
const props = defineProps<{ title: string }>();
|
|
57
|
+
const emit = defineEmits<['submit']>();
|
|
58
|
+
const active = ref(false);
|
|
59
|
+
const formattedTitle = computed(() => props.title.toUpperCase());
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<template>
|
|
63
|
+
<div class="card">
|
|
64
|
+
<h2>{{ formattedTitle }}</h2>
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
67
|
+
|
|
68
|
+
<style scoped>
|
|
69
|
+
.card {
|
|
70
|
+
background: #fff;
|
|
71
|
+
border-radius: 8px;
|
|
72
|
+
padding: 16px;
|
|
73
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
74
|
+
}
|
|
75
|
+
h2 {
|
|
76
|
+
margin: 0;
|
|
77
|
+
font-size: 18px;
|
|
78
|
+
}
|
|
79
|
+
</style>
|
|
80
|
+
`.trim();
|
|
81
|
+
const skeleton = extractCodeSkeleton(vueCode, '.vue');
|
|
82
|
+
assert.ok(skeleton !== null);
|
|
83
|
+
if (!skeleton)
|
|
84
|
+
throw new Error('Skeleton is null');
|
|
85
|
+
assert.ok(skeleton.includes('defineProps'));
|
|
86
|
+
assert.ok(skeleton.includes('defineEmits'));
|
|
87
|
+
assert.ok(skeleton.includes('ref'));
|
|
88
|
+
assert.ok(skeleton.includes('computed'));
|
|
89
|
+
assert.ok(skeleton.includes('🎨') && skeleton.includes('CSS colapsadas'));
|
|
90
|
+
});
|
|
91
|
+
it('should distill Angular components with decorators and modern Signals', () => {
|
|
92
|
+
const angularCode = `
|
|
93
|
+
import { Component, input, output, signal } from '@angular/core';
|
|
94
|
+
|
|
95
|
+
@Component({
|
|
96
|
+
selector: 'app-user-badge',
|
|
97
|
+
templateUrl: './user-badge.component.html'
|
|
98
|
+
})
|
|
99
|
+
export class UserBadgeComponent {
|
|
100
|
+
readonly userId = input.required<string>();
|
|
101
|
+
readonly statusChanged = output<boolean>();
|
|
102
|
+
readonly isOnline = signal(false);
|
|
103
|
+
|
|
104
|
+
ngOnInit() {
|
|
105
|
+
console.log('init');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public toggleStatus() {
|
|
109
|
+
this.isOnline.set(!this.isOnline());
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
`.trim();
|
|
113
|
+
const skeleton = extractCodeSkeleton(angularCode, '.ts');
|
|
114
|
+
assert.ok(skeleton !== null);
|
|
115
|
+
if (!skeleton)
|
|
116
|
+
throw new Error('Skeleton is null');
|
|
117
|
+
assert.ok(skeleton.includes('@Component'));
|
|
118
|
+
assert.ok(skeleton.includes('export class UserBadgeComponent'));
|
|
119
|
+
assert.ok(skeleton.includes('userId = input.required<string>()'));
|
|
120
|
+
assert.ok(skeleton.includes('statusChanged = output<boolean>()'));
|
|
121
|
+
assert.ok(skeleton.includes('isOnline = signal(false)'));
|
|
122
|
+
assert.ok(skeleton.includes('ngOnInit()'));
|
|
123
|
+
assert.ok(skeleton.includes('public toggleStatus()'));
|
|
124
|
+
});
|
|
125
|
+
it('should distill Astro components extracting frontmatter and props', () => {
|
|
126
|
+
const astroCode = `
|
|
127
|
+
---
|
|
128
|
+
import Header from '../components/Header.astro';
|
|
129
|
+
|
|
130
|
+
interface Props {
|
|
131
|
+
title: string;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const { title } = Astro.props;
|
|
135
|
+
---
|
|
136
|
+
<html lang="en">
|
|
137
|
+
<body>
|
|
138
|
+
<Header />
|
|
139
|
+
<h1>{title}</h1>
|
|
140
|
+
</body>
|
|
141
|
+
</html>
|
|
142
|
+
`.trim();
|
|
143
|
+
const skeleton = extractCodeSkeleton(astroCode, '.astro');
|
|
144
|
+
assert.ok(skeleton !== null);
|
|
145
|
+
if (!skeleton)
|
|
146
|
+
throw new Error('Skeleton is null');
|
|
147
|
+
assert.ok(skeleton.includes('interface Props'));
|
|
148
|
+
assert.ok(skeleton.includes('const { title } = Astro.props'));
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
//# sourceMappingURL=framework-sfc.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework-sfc.test.js","sourceRoot":"","sources":["../../tests/framework-sfc.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-collapser.test.d.ts","sourceRoot":"","sources":["../../tests/import-collapser.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { collapseImportWall } from '../src/import-collapser.js';
|
|
4
|
+
describe('Import Collapser (SPEC-002)', () => {
|
|
5
|
+
it('should keep imports intact when total imports <= 5', () => {
|
|
6
|
+
const lines = [
|
|
7
|
+
"import { useState } from 'react';",
|
|
8
|
+
"import { useEffect } from 'react';",
|
|
9
|
+
"import { Button } from './Button.js';"
|
|
10
|
+
];
|
|
11
|
+
const result = collapseImportWall(lines, '.tsx', 5);
|
|
12
|
+
assert.strictEqual(result.hasCollapsed, false);
|
|
13
|
+
assert.strictEqual(result.lines.length, 3);
|
|
14
|
+
});
|
|
15
|
+
it('should collapse import wall when total imports > 5', () => {
|
|
16
|
+
const lines = [
|
|
17
|
+
"import { Component } from '@angular/core';",
|
|
18
|
+
"import { CommonModule } from '@angular/common';",
|
|
19
|
+
"import { Observable } from 'rxjs';",
|
|
20
|
+
"import { map, filter } from 'rxjs/operators';",
|
|
21
|
+
"import { UserService } from './user.service.js';",
|
|
22
|
+
"import { UserDto } from './user.dto.js';",
|
|
23
|
+
"import { Config } from '../config.js';"
|
|
24
|
+
];
|
|
25
|
+
const result = collapseImportWall(lines, '.ts', 5);
|
|
26
|
+
assert.strictEqual(result.hasCollapsed, true);
|
|
27
|
+
assert.strictEqual(result.lines.length, 1);
|
|
28
|
+
const banner = result.lines[0];
|
|
29
|
+
assert.ok(banner.includes('[L1-L7] 📦 7 imports colapsados'));
|
|
30
|
+
assert.ok(banner.includes('@angular/core') || banner.includes('rxjs'));
|
|
31
|
+
assert.ok(banner.includes('./user.service.js') || banner.includes('./user.dto.js'));
|
|
32
|
+
assert.ok(banner.includes('Read(offset=1, limit=7)'));
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=import-collapser.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-collapser.test.js","sourceRoot":"","sources":["../../tests/import-collapser.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,KAAK,GAAG;YACZ,mCAAmC;YACnC,oCAAoC;YACpC,uCAAuC;SACxC,CAAC;QAEF,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QAC/C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,KAAK,GAAG;YACZ,4CAA4C;YAC5C,iDAAiD;YACjD,oCAAoC;YACpC,+CAA+C;YAC/C,kDAAkD;YAClD,0CAA0C;YAC1C,wCAAwC;SACzC,CAAC;QAEF,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAC9C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAE3C,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,iCAAiC,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACvE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;QACpF,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kevinbermudezc/context-guard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Intelligent context admission control and token optimization for Claude Code, Cursor, and Agentic workflows.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -32,6 +32,14 @@
|
|
|
32
32
|
],
|
|
33
33
|
"author": "Kevin Bermudez",
|
|
34
34
|
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/KevinBermudezC/context-guard.git"
|
|
38
|
+
},
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/KevinBermudezC/context-guard/issues"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/KevinBermudezC/context-guard#readme",
|
|
35
43
|
"engines": {
|
|
36
44
|
"node": ">=18.0.0"
|
|
37
45
|
},
|