@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.
Files changed (36) hide show
  1. package/README.md +15 -4
  2. package/dist/bin/claude-hook.js +19 -4
  3. package/dist/bin/claude-hook.js.map +1 -1
  4. package/dist/src/file-classifier.d.ts +15 -0
  5. package/dist/src/file-classifier.d.ts.map +1 -0
  6. package/dist/src/file-classifier.js +101 -0
  7. package/dist/src/file-classifier.js.map +1 -0
  8. package/dist/src/import-collapser.d.ts +13 -0
  9. package/dist/src/import-collapser.d.ts.map +1 -0
  10. package/dist/src/import-collapser.js +112 -0
  11. package/dist/src/import-collapser.js.map +1 -0
  12. package/dist/src/index.d.ts +2 -0
  13. package/dist/src/index.d.ts.map +1 -1
  14. package/dist/src/index.js +26 -0
  15. package/dist/src/index.js.map +1 -1
  16. package/dist/src/skeletonizer.d.ts +2 -0
  17. package/dist/src/skeletonizer.d.ts.map +1 -1
  18. package/dist/src/skeletonizer.js +86 -7
  19. package/dist/src/skeletonizer.js.map +1 -1
  20. package/dist/src/types.d.ts +1 -1
  21. package/dist/src/types.d.ts.map +1 -1
  22. package/dist/tests/claude-hook.test.js +56 -10
  23. package/dist/tests/claude-hook.test.js.map +1 -1
  24. package/dist/tests/file-classifier.test.d.ts +2 -0
  25. package/dist/tests/file-classifier.test.d.ts.map +1 -0
  26. package/dist/tests/file-classifier.test.js +46 -0
  27. package/dist/tests/file-classifier.test.js.map +1 -0
  28. package/dist/tests/framework-sfc.test.d.ts +2 -0
  29. package/dist/tests/framework-sfc.test.d.ts.map +1 -0
  30. package/dist/tests/framework-sfc.test.js +151 -0
  31. package/dist/tests/framework-sfc.test.js.map +1 -0
  32. package/dist/tests/import-collapser.test.d.ts +2 -0
  33. package/dist/tests/import-collapser.test.d.ts.map +1 -0
  34. package/dist/tests/import-collapser.test.js +35 -0
  35. package/dist/tests/import-collapser.test.js.map +1 -0
  36. 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": "View|Bash",
94
- "type": "command",
95
- "command": "node ./node_modules/@kevinbermudezc/context-guard/dist/bin/claude-hook.js"
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 `View` or bash commands 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.
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)
@@ -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 "view_file" tools
33
- if (toolName === 'View' || toolName === 'view_file') {
34
- targetFilePath = toolInput.file_path || toolInput.path || toolInput.AbsolutePath || null;
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" (o StartLine y EndLine) para inspeccionar únicamente la sección necesaria.`
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":"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"}
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;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,KAAK,UAAU,OAAO;IACpB,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,OAA0B,CAAC;IAC/B,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,oCAAoC;IACvD,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IACnD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;IAE5D,IAAI,cAAc,GAAkB,IAAI,CAAC;IACzC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,yEAAyE;IACzE,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IACnG,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,YAAY,CAAC;QACtG,cAAc,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9D,wCAAwC;QACxC,IACE,SAAS,CAAC,MAAM,KAAK,SAAS;YAC9B,SAAS,CAAC,KAAK,KAAK,SAAS;YAC7B,SAAS,CAAC,SAAS,KAAK,SAAS;YACjC,SAAS,CAAC,OAAO,KAAK,SAAS,EAC/B,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7C,0EAA0E;QAC1E,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACrG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QACxE,IAAI,QAAQ,EAAE,CAAC;YACb,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,IAAI,CAAC,cAAc,IAAI,QAAQ,EAAE,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB;IACpC,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;IACjE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,oDAAoD;IACpD,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,cAAc,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG;YACf,uCAAuC,cAAc,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG;YAC/E,cAAc,CAAC,MAAM;YACrB,EAAE;YACF,MAAM,cAAc,CAAC,iBAAiB,EAAE;SACzC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAEvC,iDAAiD;IACjD,IAAI,UAAU,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB;IACpC,CAAC;IAED,2EAA2E;IAC3E,qDAAqD;IACrD,2EAA2E;IAC3E,MAAM,QAAQ,GAAG,mBAAmB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,UAAU,UAAU,GAAG,EAAE,mCAAmC,CAAC;IAEzH,MAAM,eAAe,GAAG;QACtB,2EAA2E;QAC3E,eAAe,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,cAAc,UAAU,aAAa,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;QACnH,kIAAkI;QAClI,EAAE;QACF,2DAA2D;QAC3D,kFAAkF;QAClF,OAAO;QACP,kFAAkF;QAClF,EAAE;QACF,wBAAwB;QACxB,4KAA4K;KAC7K,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,wGAAwG;IACxG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -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":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAUzB,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,SAAS;IACT,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAC1E,oBAAoB;IACpB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IACzF,mBAAmB;IACnB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IACzC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI;IAC9D,uBAAuB;IACvB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK;CAC3E,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,gBAAgB;IAChB,mBAAmB;IACnB,WAAW;IACX,YAAY;IACZ,eAAe;IACf,cAAc;IACd,aAAa;IACb,WAAW;IACX,UAAU;CACX,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9C,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEjC,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACvB,gDAAgD;QAChD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,2EAA2E;QAC3E,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,EAAE,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YAC1D,iBAAiB,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,OAAO,iBAAiB,GAAG,QAAQ,GAAG,IAAI,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAEjD,yBAAyB;IACzB,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,OAAO;YACL,QAAQ,EAAE,UAAU;YACpB,MAAM,EAAE,eAAe,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,mCAAmC;YACjF,iBAAiB,EAAE,0GAA0G;SAC9H,CAAC;IACJ,CAAC;IAED,qCAAqC;IACrC,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAClI,OAAO;YACL,QAAQ,EAAE,UAAU;YACpB,MAAM,EAAE,eAAe,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,sCAAsC;YACpF,iBAAiB,EAAE,iGAAiG;SACrH,CAAC;IACJ,CAAC;IAED,iCAAiC;IACjC,IAAI,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,GAAG,KAAK,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACjF,OAAO;YACL,QAAQ,EAAE,QAAQ;YAClB,MAAM,EAAE,eAAe,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,4BAA4B,GAAG,IAAI;YACjF,iBAAiB,EAAE,KAAK;gBACtB,CAAC,CAAC,sFAAsF;gBACxF,CAAC,CAAC,+HAA+H;SACpI,CAAC;IACJ,CAAC;IAED,mCAAmC;IACnC,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,SAAS,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACrD,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAEjB,IAAI,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YAClD,OAAO;gBACL,QAAQ,EAAE,QAAQ;gBAClB,MAAM,EAAE,eAAe,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,+CAA+C;gBAC7F,iBAAiB,EAAE,sDAAsD;aAC1E,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;IAC5D,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,aAAa;KACxB,CAAC;AACJ,CAAC"}
@@ -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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"}
@@ -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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,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;AAElC;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAoGrG"}
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');
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
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;;;;GAIG;AAiCH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU/D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiC/E"}
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"}
@@ -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 & JavaScript
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
- // Keep top-level import/from statements
61
- if (trimmed.startsWith('import ') || trimmed.startsWith('from ') || (langKey === 'go' && trimmed.startsWith('import ('))) {
62
- skeleton.push(`[L${lineNum}] ${trimmed}`);
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
- skeleton.push(`[L${lineNum}] ${clean}`);
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":"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"}
1
+ {"version":3,"file":"skeletonizer.js","sourceRoot":"","sources":["../../src/skeletonizer.ts"],"names":[],"mappings":"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"}
@@ -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;
@@ -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 View of a file over threshold with Exit Code 2', async () => {
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: 'View',
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 View has offset and limit', async () => {
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: 'View',
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 open cat commands on large files with Exit Code 2', async () => {
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: 'Bash',
86
+ tool_name: 'View',
67
87
  tool_input: {
68
- command: `cat ${tempFile}`
88
+ file_path: tempFile,
89
+ offset: 10,
90
+ limit: 20
69
91
  }
70
92
  });
71
- assert.strictEqual(res.exitCode, 2, 'Must block raw cat with exit 2');
72
- assert.ok(res.stderr.includes('CONTEXTGUARD'));
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":"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"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=file-classifier.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=framework-sfc.test.d.ts.map
@@ -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":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,QAAQ,CAAC,mDAAmD,EAAE,GAAG,EAAE;IACjE,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAClF,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAiClB,CAAC,IAAI,EAAE,CAAC;QAET,MAAM,QAAQ,GAAG,mBAAmB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC5D,MAAM,CAAC,EAAE,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAEnD,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACrD,kCAAkC;QAClC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mFAAmF,EAAE,GAAG,EAAE;QAC3F,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4Bf,CAAC,IAAI,EAAE,CAAC;QAET,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,CAAC,EAAE,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAEnD,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;KAoBnB,CAAC,IAAI,EAAE,CAAC;QAET,MAAM,QAAQ,GAAG,mBAAmB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACzD,MAAM,CAAC,EAAE,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAEnD,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,iCAAiC,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;KAgBjB,CAAC,IAAI,EAAE,CAAC;QAET,MAAM,QAAQ,GAAG,mBAAmB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC1D,MAAM,CAAC,EAAE,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAEnD,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=import-collapser.test.d.ts.map
@@ -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.0.0",
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
  },