sigmap 6.5.0 → 6.5.2
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/AGENTS.md +113 -108
- package/CHANGELOG.md +26 -0
- package/README.md +6 -6
- package/gen-context.js +569 -3
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/core/package.json +1 -1
- package/src/config/defaults.js +3 -0
- package/src/mcp/server.js +1 -1
- package/src/retrieval/ranker.js +148 -29
package/gen-context.js
CHANGED
|
@@ -5387,7 +5387,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
|
|
|
5387
5387
|
|
|
5388
5388
|
const SERVER_INFO = {
|
|
5389
5389
|
name: 'sigmap',
|
|
5390
|
-
version: '6.5.
|
|
5390
|
+
version: '6.5.2',
|
|
5391
5391
|
description: 'SigMap MCP server — code signatures on demand',
|
|
5392
5392
|
};
|
|
5393
5393
|
|
|
@@ -7210,6 +7210,521 @@ __factories["./packages/adapters/llm-full"] = function(module, exports) {
|
|
|
7210
7210
|
module.exports = { name: 'llm-full', format, outputPath, write };
|
|
7211
7211
|
};
|
|
7212
7212
|
|
|
7213
|
+
// ── ./src/discovery/source-root-registry ──
|
|
7214
|
+
__factories["./src/discovery/source-root-registry"] = function(module, exports) {
|
|
7215
|
+
'use strict';
|
|
7216
|
+
const REGISTRY = {
|
|
7217
|
+
javascript: {
|
|
7218
|
+
manifestFiles: ['package.json'],
|
|
7219
|
+
frameworks: {
|
|
7220
|
+
nextjs: { detectionFiles: ['next.config.js','next.config.ts','next.config.mjs'], detectionDeps: ['next'], srcDirs: ['app','src/app','pages','src/pages','src','components','lib','hooks','utils'], entrypoints: ['app/page.tsx','pages/index.tsx'] },
|
|
7221
|
+
nestjs: { detectionFiles: ['nest-cli.json'], detectionDeps: ['@nestjs/core'], srcDirs: ['src'], entrypoints: ['src/main.ts','src/app.module.ts'] },
|
|
7222
|
+
express: { detectionFiles: [], detectionDeps: ['express'], srcDirs: ['src','routes','middleware','controllers','services'], entrypoints: ['src/index.js','server.js','app.js'] },
|
|
7223
|
+
fastify: { detectionFiles: [], detectionDeps: ['fastify'], srcDirs: ['src','routes','plugins'], entrypoints: ['src/index.js'] },
|
|
7224
|
+
react: { detectionFiles: [], detectionDeps: ['react'], srcDirs: ['src','components','hooks','context','pages','app','lib','utils'] },
|
|
7225
|
+
vue: { detectionFiles: ['vue.config.js','vue.config.ts'], detectionDeps: ['vue'], srcDirs: ['src','components','composables','pages','views'] },
|
|
7226
|
+
nuxt: { detectionFiles: ['nuxt.config.js','nuxt.config.ts'], detectionDeps: ['nuxt'], srcDirs: ['pages','components','composables','server','middleware','plugins'] },
|
|
7227
|
+
svelte: { detectionFiles: ['svelte.config.js'], detectionDeps: ['svelte','@sveltejs/kit'], srcDirs: ['src','src/routes','src/lib'] },
|
|
7228
|
+
angular: { detectionFiles: ['angular.json'], detectionDeps: ['@angular/core'], srcDirs: ['src','src/app','projects','apps','libs'] },
|
|
7229
|
+
gatsby: { detectionFiles: ['gatsby-config.js','gatsby-config.ts'], detectionDeps: ['gatsby'], srcDirs: ['src','gatsby'] },
|
|
7230
|
+
vite: { detectionFiles: ['vite.config.js','vite.config.ts'], detectionDeps: ['vite'], srcDirs: ['src'] },
|
|
7231
|
+
remix: { detectionFiles: ['remix.config.js'], detectionDeps: ['@remix-run/react'], srcDirs: ['app'] },
|
|
7232
|
+
trpc: { detectionFiles: [], detectionDeps: ['@trpc/server'], srcDirs: ['src','server','routers'] },
|
|
7233
|
+
},
|
|
7234
|
+
srcDirs: ['src','lib','index.js','server.js','app.js'],
|
|
7235
|
+
penalties: ['dist','build','.next','.nuxt','coverage','storybook-static'],
|
|
7236
|
+
},
|
|
7237
|
+
typescript: {
|
|
7238
|
+
manifestFiles: ['package.json','tsconfig.json'],
|
|
7239
|
+
frameworks: {
|
|
7240
|
+
nextjs: { detectionFiles: ['next.config.ts','next.config.mjs'], detectionDeps: ['next'], srcDirs: ['app','src/app','pages','src','components','lib','hooks','utils'] },
|
|
7241
|
+
nestjs: { detectionFiles: ['nest-cli.json'], detectionDeps: ['@nestjs/core'], srcDirs: ['src'], entrypoints: ['src/main.ts'] },
|
|
7242
|
+
angular: { detectionFiles: ['angular.json'], detectionDeps: ['@angular/core'], srcDirs: ['src','src/app','projects','apps','libs'] },
|
|
7243
|
+
},
|
|
7244
|
+
srcDirs: ['src','lib','packages'],
|
|
7245
|
+
penalties: ['dist','build','.next'],
|
|
7246
|
+
},
|
|
7247
|
+
python: {
|
|
7248
|
+
manifestFiles: ['requirements.txt','pyproject.toml','setup.py','Pipfile'],
|
|
7249
|
+
frameworks: {
|
|
7250
|
+
django: { detectionFiles: ['manage.py'], detectionDeps: ['Django'], srcDirs: [], specialRule: 'django-app-dirs', entrypoints: ['manage.py'] },
|
|
7251
|
+
fastapi: { detectionFiles: [], detectionDeps: ['fastapi'], srcDirs: ['app','src','routers','api'], entrypoints: ['main.py','app/main.py'] },
|
|
7252
|
+
flask: { detectionFiles: ['wsgi.py','app.py'], detectionDeps: ['Flask'], srcDirs: ['app','src'], entrypoints: ['app.py','wsgi.py'] },
|
|
7253
|
+
celery: { detectionFiles: [], detectionDeps: ['celery'], srcDirs: ['tasks','workers','app'] },
|
|
7254
|
+
},
|
|
7255
|
+
srcDirs: ['.'],
|
|
7256
|
+
penalties: ['venv','.venv','__pycache__','.pytest_cache','htmlcov'],
|
|
7257
|
+
},
|
|
7258
|
+
go: {
|
|
7259
|
+
manifestFiles: ['go.mod'],
|
|
7260
|
+
frameworks: {
|
|
7261
|
+
gin: { detectionFiles: [], detectionDeps: ['github.com/gin-gonic/gin'], srcDirs: ['internal','cmd','pkg','api','handler','middleware'] },
|
|
7262
|
+
echo: { detectionFiles: [], detectionDeps: ['github.com/labstack/echo'], srcDirs: ['internal','cmd','handler','middleware'] },
|
|
7263
|
+
fiber: { detectionFiles: [], detectionDeps: ['github.com/gofiber/fiber'], srcDirs: ['internal','cmd','handler','routes'] },
|
|
7264
|
+
grpc: { detectionFiles: [], detectionDeps: ['google.golang.org/grpc'], srcDirs: ['internal','proto','server','client'] },
|
|
7265
|
+
chi: { detectionFiles: [], detectionDeps: ['github.com/go-chi/chi'], srcDirs: ['internal','cmd','handler'] },
|
|
7266
|
+
},
|
|
7267
|
+
srcDirs: ['internal','cmd','pkg','api'],
|
|
7268
|
+
penalties: ['vendor'],
|
|
7269
|
+
},
|
|
7270
|
+
rust: {
|
|
7271
|
+
manifestFiles: ['Cargo.toml'],
|
|
7272
|
+
frameworks: {
|
|
7273
|
+
actix: { detectionFiles: [], detectionDeps: ['actix-web'], srcDirs: ['src'] },
|
|
7274
|
+
axum: { detectionFiles: [], detectionDeps: ['axum'], srcDirs: ['src'] },
|
|
7275
|
+
tauri: { detectionFiles: ['src-tauri/tauri.conf.json'], detectionDeps: ['tauri'], srcDirs: ['src','src-tauri/src'] },
|
|
7276
|
+
},
|
|
7277
|
+
srcDirs: ['src'],
|
|
7278
|
+
penalties: ['target'],
|
|
7279
|
+
},
|
|
7280
|
+
java: {
|
|
7281
|
+
manifestFiles: ['pom.xml','build.gradle'],
|
|
7282
|
+
frameworks: {
|
|
7283
|
+
spring: { detectionFiles: [], detectionDeps: ['spring-boot'], srcDirs: ['src/main/java','src/main/kotlin','src/main/resources'] },
|
|
7284
|
+
quarkus: { detectionFiles: [], detectionDeps: ['io.quarkus'], srcDirs: ['src/main/java'] },
|
|
7285
|
+
android: { detectionFiles: ['AndroidManifest.xml'], srcDirs: ['app/src/main/java','app/src/main','src'] },
|
|
7286
|
+
micronaut:{ detectionFiles: [], detectionDeps: ['io.micronaut'],srcDirs: ['src/main/java'] },
|
|
7287
|
+
},
|
|
7288
|
+
srcDirs: ['src/main/java','src'],
|
|
7289
|
+
penalties: ['target','build'],
|
|
7290
|
+
},
|
|
7291
|
+
kotlin: {
|
|
7292
|
+
manifestFiles: ['build.gradle.kts'],
|
|
7293
|
+
frameworks: {
|
|
7294
|
+
spring: { detectionFiles: [], detectionDeps: ['spring-boot'], srcDirs: ['src/main/kotlin'] },
|
|
7295
|
+
android: { detectionFiles: ['AndroidManifest.xml'], srcDirs: ['app/src/main/kotlin','app/src/main/java'] },
|
|
7296
|
+
ktor: { detectionFiles: [], detectionDeps: ['io.ktor'], srcDirs: ['src'] },
|
|
7297
|
+
compose: { detectionFiles: [], detectionDeps: ['compose-runtime'], srcDirs: ['app/src/main/kotlin','src'] },
|
|
7298
|
+
},
|
|
7299
|
+
srcDirs: ['src/main/kotlin','src'],
|
|
7300
|
+
penalties: ['build','.gradle'],
|
|
7301
|
+
},
|
|
7302
|
+
csharp: {
|
|
7303
|
+
manifestFiles: ['.csproj','.sln'],
|
|
7304
|
+
frameworks: {
|
|
7305
|
+
aspnet: { detectionFiles: ['appsettings.json'], detectionDeps: ['Microsoft.AspNetCore'], srcDirs: ['Controllers','Services','Models','Middleware','Pages'] },
|
|
7306
|
+
blazor: { detectionFiles: [], detectionDeps: ['Microsoft.AspNetCore.Components'], srcDirs: ['Components','Pages','Services'] },
|
|
7307
|
+
unity: { detectionFiles: ['ProjectSettings/ProjectSettings.asset'], srcDirs: ['Assets/Scripts','Assets'] },
|
|
7308
|
+
maui: { detectionFiles: [], detectionDeps: ['Microsoft.Maui'], srcDirs: ['src','Pages','ViewModels'] },
|
|
7309
|
+
},
|
|
7310
|
+
srcDirs: ['src','Controllers','Services','Models'],
|
|
7311
|
+
penalties: ['bin','obj','.vs'],
|
|
7312
|
+
},
|
|
7313
|
+
php: {
|
|
7314
|
+
manifestFiles: ['composer.json'],
|
|
7315
|
+
frameworks: {
|
|
7316
|
+
laravel: { detectionFiles: ['artisan'], srcDirs: ['app','routes','config','database','resources','tests'], entrypoints: ['artisan'] },
|
|
7317
|
+
symfony: { detectionFiles: ['symfony.lock'], srcDirs: ['src','config','templates'], specialRule: 'symfony-bundle-dirs' },
|
|
7318
|
+
wordpress: { detectionFiles: ['wp-config.php'], srcDirs: ['wp-content/themes','wp-content/plugins','wp-content/mu-plugins'] },
|
|
7319
|
+
slim: { detectionFiles: [], detectionDeps: ['slim/slim'], srcDirs: ['src','app','routes'] },
|
|
7320
|
+
},
|
|
7321
|
+
srcDirs: ['src','app'],
|
|
7322
|
+
penalties: ['vendor'],
|
|
7323
|
+
},
|
|
7324
|
+
ruby: {
|
|
7325
|
+
manifestFiles: ['Gemfile'],
|
|
7326
|
+
frameworks: {
|
|
7327
|
+
rails: { detectionFiles: ['config/routes.rb'], srcDirs: ['app','lib','config','db','spec','test'], entrypoints: ['config/routes.rb'] },
|
|
7328
|
+
sinatra: { detectionFiles: ['config.ru','app.rb'], srcDirs: ['.','lib'], entrypoints: ['app.rb','config.ru'] },
|
|
7329
|
+
hanami: { detectionFiles: [], detectionDeps: ['hanami'], srcDirs: ['apps','lib','slices'] },
|
|
7330
|
+
},
|
|
7331
|
+
srcDirs: ['app','lib'],
|
|
7332
|
+
penalties: ['vendor','coverage','.bundle'],
|
|
7333
|
+
},
|
|
7334
|
+
swift: {
|
|
7335
|
+
manifestFiles: ['Package.swift'],
|
|
7336
|
+
frameworks: {
|
|
7337
|
+
vapor: { detectionFiles: [], detectionDeps: ['vapor/vapor'], srcDirs: ['Sources','App'] },
|
|
7338
|
+
swiftui: { detectionFiles: ['.xcodeproj'], srcDirs: [], specialRule: 'swift-project-dir' },
|
|
7339
|
+
swiftpm: { detectionFiles: ['Package.swift'],srcDirs: ['Sources'] },
|
|
7340
|
+
},
|
|
7341
|
+
srcDirs: ['Sources','Source'],
|
|
7342
|
+
penalties: ['.build','DerivedData','Pods','Carthage'],
|
|
7343
|
+
},
|
|
7344
|
+
dart: {
|
|
7345
|
+
manifestFiles: ['pubspec.yaml'],
|
|
7346
|
+
frameworks: {
|
|
7347
|
+
flutter: { detectionFiles: [], detectionDeps: ['flutter'], srcDirs: ['lib','lib/src'], entrypoints: ['lib/main.dart'] },
|
|
7348
|
+
serverpod: { detectionFiles: [], detectionDeps: ['serverpod'], srcDirs: ['lib','endpoints','models'] },
|
|
7349
|
+
'dart-frog':{ detectionFiles: ['dart_frog.yaml'], srcDirs: ['routes','lib'] },
|
|
7350
|
+
},
|
|
7351
|
+
srcDirs: ['lib','lib/src'],
|
|
7352
|
+
penalties: ['.dart_tool','build'],
|
|
7353
|
+
},
|
|
7354
|
+
scala: {
|
|
7355
|
+
manifestFiles: ['build.sbt'],
|
|
7356
|
+
frameworks: {
|
|
7357
|
+
akka: { detectionFiles: [], detectionDeps: ['akka'], srcDirs: ['src/main/scala','src'] },
|
|
7358
|
+
play: { detectionFiles: [], detectionDeps: ['play'], srcDirs: ['app','conf'] },
|
|
7359
|
+
spark: { detectionFiles: [], detectionDeps: ['spark'],srcDirs: ['src/main/scala'] },
|
|
7360
|
+
zio: { detectionFiles: [], detectionDeps: ['zio'], srcDirs: ['src/main/scala'] },
|
|
7361
|
+
},
|
|
7362
|
+
srcDirs: ['src/main/scala','src'],
|
|
7363
|
+
penalties: ['target'],
|
|
7364
|
+
},
|
|
7365
|
+
};
|
|
7366
|
+
module.exports = { REGISTRY };
|
|
7367
|
+
};
|
|
7368
|
+
|
|
7369
|
+
// ── ./src/discovery/sigmapignore ──
|
|
7370
|
+
__factories["./src/discovery/sigmapignore"] = function(module, exports) {
|
|
7371
|
+
'use strict';
|
|
7372
|
+
const fs = require('fs');
|
|
7373
|
+
const path = require('path');
|
|
7374
|
+
function loadIgnorePatterns(cwd) {
|
|
7375
|
+
for (const fname of ['.sigmapignore', '.contextignore']) {
|
|
7376
|
+
const p = path.join(cwd, fname);
|
|
7377
|
+
if (fs.existsSync(p)) {
|
|
7378
|
+
return fs.readFileSync(p, 'utf8')
|
|
7379
|
+
.split('\n')
|
|
7380
|
+
.map(l => l.trim())
|
|
7381
|
+
.filter(l => l && !l.startsWith('#'));
|
|
7382
|
+
}
|
|
7383
|
+
}
|
|
7384
|
+
return [];
|
|
7385
|
+
}
|
|
7386
|
+
function matchesIgnorePattern(dirName, patterns) {
|
|
7387
|
+
for (const pat of patterns) {
|
|
7388
|
+
const clean = pat.replace(/\/$/, '');
|
|
7389
|
+
if (clean === dirName) return true;
|
|
7390
|
+
if (clean.endsWith('/**') && dirName.startsWith(clean.slice(0, -3))) return true;
|
|
7391
|
+
if (clean.endsWith('/*') && dirName.startsWith(clean.slice(0, -2))) return true;
|
|
7392
|
+
}
|
|
7393
|
+
return false;
|
|
7394
|
+
}
|
|
7395
|
+
module.exports = { loadIgnorePatterns, matchesIgnorePattern };
|
|
7396
|
+
};
|
|
7397
|
+
|
|
7398
|
+
// ── ./src/discovery/language-detector ──
|
|
7399
|
+
__factories["./src/discovery/language-detector"] = function(module, exports) {
|
|
7400
|
+
'use strict';
|
|
7401
|
+
const fs = require('fs');
|
|
7402
|
+
const path = require('path');
|
|
7403
|
+
const { REGISTRY } = __require('./src/discovery/source-root-registry');
|
|
7404
|
+
function detectLanguages(cwd) {
|
|
7405
|
+
const weights = {};
|
|
7406
|
+
for (const [lang, reg] of Object.entries(REGISTRY)) {
|
|
7407
|
+
for (const mf of (reg.manifestFiles || [])) {
|
|
7408
|
+
if (fs.existsSync(path.join(cwd, mf))) {
|
|
7409
|
+
weights[lang] = (weights[lang] || 0) + 3;
|
|
7410
|
+
}
|
|
7411
|
+
}
|
|
7412
|
+
}
|
|
7413
|
+
try {
|
|
7414
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
|
|
7415
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
7416
|
+
if (allDeps.typescript) { weights.typescript = (weights.typescript || 0) + 2; }
|
|
7417
|
+
} catch (_) {}
|
|
7418
|
+
const extCount = {};
|
|
7419
|
+
(function _walkDepth(dir, depth, extCount) {
|
|
7420
|
+
if (depth <= 0) return;
|
|
7421
|
+
let entries;
|
|
7422
|
+
try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch (_) { return; }
|
|
7423
|
+
for (const e of entries) {
|
|
7424
|
+
const SKIP_DIRS = new Set(['node_modules','dist','build','.git','.next','.nuxt','vendor','DerivedData','Pods','target','coverage','__pycache__','.venv','venv','.build','Carthage','storybook-static']);
|
|
7425
|
+
if (SKIP_DIRS.has(e.name)) continue;
|
|
7426
|
+
if (e.isDirectory()) {
|
|
7427
|
+
_walkDepth(path.join(dir, e.name), depth - 1, extCount);
|
|
7428
|
+
} else if (e.isFile()) {
|
|
7429
|
+
const EXT_TO_LANG = {'.js': 'javascript', '.mjs': 'javascript', '.cjs': 'javascript', '.ts': 'typescript', '.tsx': 'typescript', '.jsx': 'javascript', '.py': 'python', '.rb': 'ruby', '.go': 'go', '.rs': 'rust', '.java': 'java', '.kt': 'kotlin', '.cs': 'csharp', '.cpp': 'cpp', '.c': 'cpp', '.h': 'cpp', '.hpp': 'cpp', '.swift': 'swift', '.dart': 'dart', '.scala': 'scala', '.php': 'php'};
|
|
7430
|
+
const ext = path.extname(e.name).toLowerCase();
|
|
7431
|
+
if (EXT_TO_LANG[ext]) extCount[ext] = (extCount[ext] || 0) + 1;
|
|
7432
|
+
}
|
|
7433
|
+
}
|
|
7434
|
+
})(cwd, 3, extCount);
|
|
7435
|
+
const maxCount = Math.max(1, ...Object.values(extCount));
|
|
7436
|
+
const EXT_TO_LANG = {'.js': 'javascript', '.mjs': 'javascript', '.cjs': 'javascript', '.ts': 'typescript', '.tsx': 'typescript', '.jsx': 'javascript', '.py': 'python', '.rb': 'ruby', '.go': 'go', '.rs': 'rust', '.java': 'java', '.kt': 'kotlin', '.cs': 'csharp', '.cpp': 'cpp', '.c': 'cpp', '.h': 'cpp', '.hpp': 'cpp', '.swift': 'swift', '.dart': 'dart', '.scala': 'scala', '.php': 'php'};
|
|
7437
|
+
for (const [ext, count] of Object.entries(extCount)) {
|
|
7438
|
+
const lang = EXT_TO_LANG[ext];
|
|
7439
|
+
if (lang) {
|
|
7440
|
+
weights[lang] = (weights[lang] || 0) + Math.min(5, (count / maxCount) * 5);
|
|
7441
|
+
}
|
|
7442
|
+
}
|
|
7443
|
+
const maxW = Math.max(1, ...Object.values(weights));
|
|
7444
|
+
return Object.entries(weights)
|
|
7445
|
+
.map(([name, w]) => ({ name, weight: Math.round(w / maxW * 100) / 100 }))
|
|
7446
|
+
.sort((a, b) => b.weight - a.weight);
|
|
7447
|
+
}
|
|
7448
|
+
module.exports = { detectLanguages };
|
|
7449
|
+
};
|
|
7450
|
+
|
|
7451
|
+
// ── ./src/discovery/source-root-scorer ──
|
|
7452
|
+
__factories["./src/discovery/source-root-scorer"] = function(module, exports) {
|
|
7453
|
+
'use strict';
|
|
7454
|
+
const fs = require('fs');
|
|
7455
|
+
const path = require('path');
|
|
7456
|
+
const { execSync } = require('child_process');
|
|
7457
|
+
const CODE_EXTS = new Set(['.js','.mjs','.cjs','.ts','.tsx','.jsx','.py','.rb','.go','.rs','.java','.kt','.cs','.cpp','.c','.h','.swift','.dart','.scala','.php']);
|
|
7458
|
+
const AUTO_SKIP = new Set(['node_modules','dist','build','.git','.next','.nuxt','vendor','DerivedData','Pods','target','coverage','__pycache__','.venv','venv','.build','Carthage','storybook-static','.gradle','bin','obj','.vs']);
|
|
7459
|
+
const PENALTY_DIRS = new Set(['test','tests','spec','__tests__','e2e','docs','doc','docs-vp','examples','example','fixtures','mocks','__mocks__','demo','samples','migrations','benchmarks','scripts']);
|
|
7460
|
+
const ROOT_ENTRYPOINTS = { go: ['main.go'], python: ['app.py','main.py','wsgi.py','asgi.py'], javascript: ['index.js','server.js','app.js'], typescript: ['index.ts','main.ts'], rust: [], php: ['index.php'] };
|
|
7461
|
+
function getRecentlyChangedDirs(cwd) {
|
|
7462
|
+
try {
|
|
7463
|
+
const out = execSync('git log --name-only --format="" HEAD~10 2>/dev/null', { cwd, timeout: 3000 }).toString();
|
|
7464
|
+
return new Set(out.split('\n').filter(Boolean).map(f => f.split('/')[0]));
|
|
7465
|
+
} catch { return new Set(); }
|
|
7466
|
+
}
|
|
7467
|
+
function scoreCandidate(dirName, fullPath, context) {
|
|
7468
|
+
const { frameworks, languages, recentDirs, frameworkSrcDirs, entrypoints, frameworkPenalties } = context;
|
|
7469
|
+
if (AUTO_SKIP.has(dirName)) return -99;
|
|
7470
|
+
if (!fs.existsSync(fullPath)) return -99;
|
|
7471
|
+
let score = 0;
|
|
7472
|
+
if (frameworkSrcDirs.has(dirName)) score += 3.0;
|
|
7473
|
+
const sourceFileCount = (function _countSourceFiles(dir, depth) {
|
|
7474
|
+
if (depth <= 0) return 0;
|
|
7475
|
+
let count = 0;
|
|
7476
|
+
try {
|
|
7477
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
7478
|
+
if (e.isFile() && CODE_EXTS.has(path.extname(e.name).toLowerCase())) count++;
|
|
7479
|
+
else if (e.isDirectory() && depth > 1) count += _countSourceFiles(path.join(dir, e.name), depth - 1);
|
|
7480
|
+
}
|
|
7481
|
+
} catch (_) {}
|
|
7482
|
+
return count;
|
|
7483
|
+
})(fullPath, 2);
|
|
7484
|
+
const density = Math.min(1.0, sourceFileCount / 10);
|
|
7485
|
+
score += density * 2.5;
|
|
7486
|
+
if (sourceFileCount >= 3) score += 2.0;
|
|
7487
|
+
if ((entrypoints || []).some(ep => ep.startsWith(dirName + '/'))) score += 1.5;
|
|
7488
|
+
if (fs.existsSync(path.join(fullPath, 'package.json')) ||
|
|
7489
|
+
fs.existsSync(path.join(fullPath, 'go.mod')) ||
|
|
7490
|
+
fs.existsSync(path.join(fullPath, 'Cargo.toml')) ||
|
|
7491
|
+
fs.existsSync(path.join(fullPath, 'pom.xml'))) {
|
|
7492
|
+
score += 1.0;
|
|
7493
|
+
}
|
|
7494
|
+
if (recentDirs.has(dirName)) score += 2.0;
|
|
7495
|
+
if (PENALTY_DIRS.has(dirName.toLowerCase()) && !frameworkSrcDirs.has(dirName)) score -= 3.0;
|
|
7496
|
+
if ((frameworkPenalties || []).includes(dirName)) score -= 3.0;
|
|
7497
|
+
return Math.round(score * 100) / 100;
|
|
7498
|
+
}
|
|
7499
|
+
module.exports = { scoreCandidate, getRecentlyChangedDirs, ROOT_ENTRYPOINTS };
|
|
7500
|
+
};
|
|
7501
|
+
|
|
7502
|
+
// ── ./src/discovery/framework-detector ──
|
|
7503
|
+
__factories["./src/discovery/framework-detector"] = function(module, exports) {
|
|
7504
|
+
'use strict';
|
|
7505
|
+
const fs = require('fs');
|
|
7506
|
+
const path = require('path');
|
|
7507
|
+
const { REGISTRY } = __require('./src/discovery/source-root-registry');
|
|
7508
|
+
function detectFrameworks(cwd) {
|
|
7509
|
+
const detected = [];
|
|
7510
|
+
for (const [lang, reg] of Object.entries(REGISTRY)) {
|
|
7511
|
+
if (!reg.frameworks) continue;
|
|
7512
|
+
for (const [name, fw] of Object.entries(reg.frameworks)) {
|
|
7513
|
+
let confidence = 0;
|
|
7514
|
+
for (const f of (fw.detectionFiles || [])) {
|
|
7515
|
+
if ((function _existsAnywhere(cwd, filename, maxDepth) {
|
|
7516
|
+
const parts = filename.split('/');
|
|
7517
|
+
if (parts.length > 1) return fs.existsSync(path.join(cwd, filename));
|
|
7518
|
+
return (function _walkFind(dir, name, depth) {
|
|
7519
|
+
if (depth <= 0) return false;
|
|
7520
|
+
try {
|
|
7521
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
7522
|
+
for (const e of entries) {
|
|
7523
|
+
if (e.name === name) return true;
|
|
7524
|
+
if (e.isDirectory() && depth > 1) {
|
|
7525
|
+
if (_walkFind(path.join(dir, e.name), name, depth - 1)) return true;
|
|
7526
|
+
}
|
|
7527
|
+
}
|
|
7528
|
+
} catch (_) {}
|
|
7529
|
+
return false;
|
|
7530
|
+
})(cwd, parts[0], maxDepth);
|
|
7531
|
+
})(cwd, f, 3)) { confidence = Math.max(confidence, 0.93); }
|
|
7532
|
+
}
|
|
7533
|
+
if (fw.detectionDeps?.length) {
|
|
7534
|
+
const deps = (function _readDeps(cwd) {
|
|
7535
|
+
try {
|
|
7536
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
|
|
7537
|
+
return new Set([...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.devDependencies || {})]);
|
|
7538
|
+
} catch { return new Set(); }
|
|
7539
|
+
})(cwd);
|
|
7540
|
+
for (const dep of fw.detectionDeps) {
|
|
7541
|
+
if (deps.has(dep)) { confidence = Math.max(confidence, 0.90); }
|
|
7542
|
+
}
|
|
7543
|
+
}
|
|
7544
|
+
if (lang === 'go' && fw.detectionDeps?.length) {
|
|
7545
|
+
const goMod = (function _readFile(p) {
|
|
7546
|
+
try { return fs.readFileSync(p, 'utf8'); } catch { return ''; }
|
|
7547
|
+
})(path.join(cwd, 'go.mod'));
|
|
7548
|
+
for (const dep of fw.detectionDeps) {
|
|
7549
|
+
if (goMod.includes(dep)) { confidence = Math.max(confidence, 0.90); }
|
|
7550
|
+
}
|
|
7551
|
+
}
|
|
7552
|
+
if (lang === 'rust' && fw.detectionDeps?.length) {
|
|
7553
|
+
const cargoToml = (function _readFile(p) {
|
|
7554
|
+
try { return fs.readFileSync(p, 'utf8'); } catch { return ''; }
|
|
7555
|
+
})(path.join(cwd, 'Cargo.toml'));
|
|
7556
|
+
for (const dep of fw.detectionDeps) {
|
|
7557
|
+
if (cargoToml.includes(dep)) { confidence = Math.max(confidence, 0.88); }
|
|
7558
|
+
}
|
|
7559
|
+
}
|
|
7560
|
+
if (fw.specialRule === 'django-app-dirs' && fs.existsSync(path.join(cwd, 'manage.py'))) {
|
|
7561
|
+
confidence = Math.max(confidence, 0.95);
|
|
7562
|
+
}
|
|
7563
|
+
if (fw.specialRule === 'swift-project-dir' && (function _existsAnywhere(cwd, filename, maxDepth) {
|
|
7564
|
+
const parts = filename.split('/');
|
|
7565
|
+
if (parts.length > 1) return fs.existsSync(path.join(cwd, filename));
|
|
7566
|
+
return (function _walkFind(dir, name, depth) {
|
|
7567
|
+
if (depth <= 0) return false;
|
|
7568
|
+
try {
|
|
7569
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
7570
|
+
for (const e of entries) {
|
|
7571
|
+
if (e.name === name) return true;
|
|
7572
|
+
if (e.isDirectory() && depth > 1) {
|
|
7573
|
+
if (_walkFind(path.join(dir, e.name), name, depth - 1)) return true;
|
|
7574
|
+
}
|
|
7575
|
+
}
|
|
7576
|
+
} catch (_) {}
|
|
7577
|
+
return false;
|
|
7578
|
+
})(cwd, parts[0], maxDepth);
|
|
7579
|
+
})(cwd, '.xcodeproj', 2)) {
|
|
7580
|
+
confidence = Math.max(confidence, 0.90);
|
|
7581
|
+
}
|
|
7582
|
+
if (confidence > 0) detected.push({ name, language: lang, confidence });
|
|
7583
|
+
}
|
|
7584
|
+
}
|
|
7585
|
+
return detected.sort((a, b) => b.confidence - a.confidence);
|
|
7586
|
+
}
|
|
7587
|
+
module.exports = { detectFrameworks };
|
|
7588
|
+
};
|
|
7589
|
+
|
|
7590
|
+
// ── ./src/discovery/source-root-resolver ──
|
|
7591
|
+
__factories["./src/discovery/source-root-resolver"] = function(module, exports) {
|
|
7592
|
+
'use strict';
|
|
7593
|
+
const fs = require('fs');
|
|
7594
|
+
const path = require('path');
|
|
7595
|
+
const { REGISTRY } = __require('./src/discovery/source-root-registry');
|
|
7596
|
+
const { detectLanguages } = __require('./src/discovery/language-detector');
|
|
7597
|
+
const { detectFrameworks } = __require('./src/discovery/framework-detector');
|
|
7598
|
+
const { scoreCandidate, getRecentlyChangedDirs, ROOT_ENTRYPOINTS } = __require('./src/discovery/source-root-scorer');
|
|
7599
|
+
const { loadIgnorePatterns, matchesIgnorePattern } = __require('./src/discovery/sigmapignore');
|
|
7600
|
+
function resolveSourceRoots(cwd, opts = {}) {
|
|
7601
|
+
const ignorePatterns = loadIgnorePatterns(cwd);
|
|
7602
|
+
const languages = detectLanguages(cwd);
|
|
7603
|
+
const frameworks = detectFrameworks(cwd);
|
|
7604
|
+
const recentDirs = getRecentlyChangedDirs(cwd);
|
|
7605
|
+
const isMonorepo = (function _detectMonorepo(cwd) {
|
|
7606
|
+
const MONOREPO_MARKERS = ['pnpm-workspace.yaml','turbo.json','nx.json','lerna.json'];
|
|
7607
|
+
for (const m of MONOREPO_MARKERS) {
|
|
7608
|
+
if (fs.existsSync(path.join(cwd, m))) return true;
|
|
7609
|
+
}
|
|
7610
|
+
try {
|
|
7611
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
|
|
7612
|
+
if (pkg.workspaces) return true;
|
|
7613
|
+
} catch (_) {}
|
|
7614
|
+
return false;
|
|
7615
|
+
})(cwd);
|
|
7616
|
+
const primaryLang = languages[0]?.name;
|
|
7617
|
+
const primaryFw = frameworks[0];
|
|
7618
|
+
const registry = primaryLang ? REGISTRY[primaryLang] : null;
|
|
7619
|
+
const fwEntry = primaryFw && registry?.frameworks?.[primaryFw.name];
|
|
7620
|
+
const frameworkSrcDirs = new Set(fwEntry?.srcDirs || registry?.srcDirs || []);
|
|
7621
|
+
const entrypoints = fwEntry?.entrypoints || [];
|
|
7622
|
+
const frameworkPenalties = registry?.penalties || [];
|
|
7623
|
+
const context = { frameworks, languages, recentDirs, frameworkSrcDirs, entrypoints, frameworkPenalties };
|
|
7624
|
+
const candidates = (function _enumerateCandidates(cwd, isMonorepo, ignorePatterns, excludeList) {
|
|
7625
|
+
const candidates = [];
|
|
7626
|
+
const excSet = new Set(excludeList);
|
|
7627
|
+
try {
|
|
7628
|
+
for (const e of fs.readdirSync(cwd, { withFileTypes: true })) {
|
|
7629
|
+
if (!e.isDirectory()) continue;
|
|
7630
|
+
if (excSet.has(e.name)) continue;
|
|
7631
|
+
if (matchesIgnorePattern(e.name, ignorePatterns)) continue;
|
|
7632
|
+
candidates.push({ name: e.name, full: path.join(cwd, e.name) });
|
|
7633
|
+
}
|
|
7634
|
+
} catch (_) {}
|
|
7635
|
+
if (isMonorepo) {
|
|
7636
|
+
for (const top of ['packages','apps','services','modules']) {
|
|
7637
|
+
const topFull = path.join(cwd, top);
|
|
7638
|
+
if (!fs.existsSync(topFull)) continue;
|
|
7639
|
+
try {
|
|
7640
|
+
for (const pkg of fs.readdirSync(topFull, { withFileTypes: true })) {
|
|
7641
|
+
if (!pkg.isDirectory()) continue;
|
|
7642
|
+
const srcFull = path.join(topFull, pkg.name, 'src');
|
|
7643
|
+
if (fs.existsSync(srcFull)) {
|
|
7644
|
+
candidates.push({ name: `${top}/${pkg.name}/src`, full: srcFull });
|
|
7645
|
+
}
|
|
7646
|
+
candidates.push({ name: `${top}/${pkg.name}`, full: path.join(topFull, pkg.name) });
|
|
7647
|
+
}
|
|
7648
|
+
} catch (_) {}
|
|
7649
|
+
}
|
|
7650
|
+
}
|
|
7651
|
+
const DEEP_PATHS = ['src/main/java','src/main/kotlin','src/main/scala','src-tauri/src','Sources/App','app/src/main/java','app/src/main/kotlin'];
|
|
7652
|
+
for (const dp of DEEP_PATHS) {
|
|
7653
|
+
const full = path.join(cwd, dp);
|
|
7654
|
+
if (fs.existsSync(full)) candidates.push({ name: dp, full });
|
|
7655
|
+
}
|
|
7656
|
+
return candidates;
|
|
7657
|
+
})(cwd, isMonorepo, ignorePatterns, opts.exclude || []);
|
|
7658
|
+
const scored = candidates
|
|
7659
|
+
.map(({ name, full }) => ({
|
|
7660
|
+
dir: name,
|
|
7661
|
+
full,
|
|
7662
|
+
score: scoreCandidate(name, full, context),
|
|
7663
|
+
}))
|
|
7664
|
+
.filter(c => c.score > 0)
|
|
7665
|
+
.sort((a, b) => b.score - a.score);
|
|
7666
|
+
let roots = (function _applySpecialRules(scored, cwd, primaryFw, fwEntry, frameworks) {
|
|
7667
|
+
let roots = [...scored];
|
|
7668
|
+
if (primaryFw?.name === 'django' || frameworks.some(f => f.name === 'django')) {
|
|
7669
|
+
try {
|
|
7670
|
+
for (const e of fs.readdirSync(cwd, { withFileTypes: true })) {
|
|
7671
|
+
if (!e.isDirectory()) continue;
|
|
7672
|
+
const d = path.join(cwd, e.name);
|
|
7673
|
+
if (fs.existsSync(path.join(d, 'models.py')) || fs.existsSync(path.join(d, 'views.py'))) {
|
|
7674
|
+
if (!roots.find(r => r.dir === e.name)) {
|
|
7675
|
+
roots.push({ dir: e.name, full: d, score: 5.0 });
|
|
7676
|
+
}
|
|
7677
|
+
}
|
|
7678
|
+
}
|
|
7679
|
+
} catch (_) {}
|
|
7680
|
+
roots.sort((a, b) => b.score - a.score);
|
|
7681
|
+
}
|
|
7682
|
+
if (frameworks.some(f => f.name === 'swiftui')) {
|
|
7683
|
+
try {
|
|
7684
|
+
for (const e of fs.readdirSync(cwd, { withFileTypes: true })) {
|
|
7685
|
+
if (!e.isDirectory()) continue;
|
|
7686
|
+
const d = path.join(cwd, e.name);
|
|
7687
|
+
const swiftCount = (fs.readdirSync(d).filter(f => f.endsWith('.swift'))).length;
|
|
7688
|
+
if (swiftCount >= 3 && !roots.find(r => r.dir === e.name)) {
|
|
7689
|
+
roots.push({ dir: e.name, full: d, score: 4.0 });
|
|
7690
|
+
}
|
|
7691
|
+
}
|
|
7692
|
+
} catch (_) {}
|
|
7693
|
+
roots.sort((a, b) => b.score - a.score);
|
|
7694
|
+
}
|
|
7695
|
+
return roots;
|
|
7696
|
+
})(scored, cwd, primaryFw, fwEntry, frameworks);
|
|
7697
|
+
roots = (function _dedupeNested(scored) {
|
|
7698
|
+
const result = [];
|
|
7699
|
+
for (const c of scored) {
|
|
7700
|
+
const isNested = result.some(r => c.dir.startsWith(r.dir + '/'));
|
|
7701
|
+
if (!isNested) result.push(c);
|
|
7702
|
+
}
|
|
7703
|
+
return result;
|
|
7704
|
+
})(roots);
|
|
7705
|
+
const MAX_ROOTS = 6;
|
|
7706
|
+
roots = roots.slice(0, MAX_ROOTS).map(r => r.dir);
|
|
7707
|
+
const confidence = (function _computeConfidence(frameworks, languages, scoredCount) {
|
|
7708
|
+
if (frameworks.length > 0 && frameworks[0].confidence >= 0.90) return 'high';
|
|
7709
|
+
if (languages.length > 0 && scoredCount > 0) return 'medium';
|
|
7710
|
+
return 'low';
|
|
7711
|
+
})(frameworks, languages, scored.length);
|
|
7712
|
+
return {
|
|
7713
|
+
roots,
|
|
7714
|
+
languages,
|
|
7715
|
+
frameworks,
|
|
7716
|
+
confidence,
|
|
7717
|
+
explanation: scored.slice(0, 8).map(c => ({
|
|
7718
|
+
dir: c.dir,
|
|
7719
|
+
score: c.score,
|
|
7720
|
+
reason: `score: ${c.score}`,
|
|
7721
|
+
})),
|
|
7722
|
+
isMonorepo,
|
|
7723
|
+
};
|
|
7724
|
+
}
|
|
7725
|
+
module.exports = { resolveSourceRoots };
|
|
7726
|
+
};
|
|
7727
|
+
|
|
7213
7728
|
/**
|
|
7214
7729
|
* SigMap — gen-context.js v1.2.0
|
|
7215
7730
|
* Zero-dependency AI context engine.
|
|
@@ -7222,7 +7737,7 @@ const path = require('path');
|
|
|
7222
7737
|
const os = require('os');
|
|
7223
7738
|
const { execSync } = require('child_process');
|
|
7224
7739
|
|
|
7225
|
-
const VERSION = '6.5.
|
|
7740
|
+
const VERSION = '6.5.2';
|
|
7226
7741
|
const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
|
|
7227
7742
|
|
|
7228
7743
|
function requireSourceOrBundled(key) {
|
|
@@ -8429,6 +8944,13 @@ function runGenerate(cwd, config, reportMode, reportJson = false) {
|
|
|
8429
8944
|
const hotCommits = config.hotCommits || 10;
|
|
8430
8945
|
const recentFiles = config.diffPriority ? getRecentlyCommittedFiles(cwd, hotCommits) : new Set();
|
|
8431
8946
|
|
|
8947
|
+
// v6.7: Load signature cache if enabled
|
|
8948
|
+
let cache = null;
|
|
8949
|
+
const { loadCache, saveCache, getChangedFiles, updateCacheEntries } = requireSourceOrBundled('./src/cache/sig-cache');
|
|
8950
|
+
if (config.sigCache) {
|
|
8951
|
+
cache = loadCache(cwd, VERSION);
|
|
8952
|
+
}
|
|
8953
|
+
|
|
8432
8954
|
let inputTokenTotal = 0;
|
|
8433
8955
|
let fileEntries = [];
|
|
8434
8956
|
let testIndex = null;
|
|
@@ -8449,7 +8971,23 @@ function runGenerate(cwd, config, reportMode, reportJson = false) {
|
|
|
8449
8971
|
continue;
|
|
8450
8972
|
}
|
|
8451
8973
|
|
|
8452
|
-
|
|
8974
|
+
// v6.7: Check cache before extracting
|
|
8975
|
+
let sigs = [];
|
|
8976
|
+
if (cache) {
|
|
8977
|
+
const cached = cache.get(filePath);
|
|
8978
|
+
let mtime = 0;
|
|
8979
|
+
try { mtime = fs.statSync(filePath).mtimeMs; } catch (_) {}
|
|
8980
|
+
if (cached && cached.mtime === mtime) {
|
|
8981
|
+
sigs = cached.sigs;
|
|
8982
|
+
} else {
|
|
8983
|
+
sigs = detectAndExtract(filePath, content, config.maxSigsPerFile);
|
|
8984
|
+
if (sigs.length > 0) {
|
|
8985
|
+
cache.set(filePath, { mtime, sigs });
|
|
8986
|
+
}
|
|
8987
|
+
}
|
|
8988
|
+
} else {
|
|
8989
|
+
sigs = detectAndExtract(filePath, content, config.maxSigsPerFile);
|
|
8990
|
+
}
|
|
8453
8991
|
if (sigs.length === 0) continue;
|
|
8454
8992
|
|
|
8455
8993
|
// Baseline = estimated tokens of original source content for intuitive reduction stats.
|
|
@@ -8651,6 +9189,15 @@ function runGenerate(cwd, config, reportMode, reportJson = false) {
|
|
|
8651
9189
|
process.stderr.write(lines.join('\n'));
|
|
8652
9190
|
}
|
|
8653
9191
|
|
|
9192
|
+
// v6.7: Save cache if enabled
|
|
9193
|
+
if (config.sigCache && cache) {
|
|
9194
|
+
try {
|
|
9195
|
+
saveCache(cwd, VERSION, cache);
|
|
9196
|
+
} catch (err) {
|
|
9197
|
+
console.warn(`[sigmap] cache save failed: ${err.message}`);
|
|
9198
|
+
}
|
|
9199
|
+
}
|
|
9200
|
+
|
|
8654
9201
|
return result;
|
|
8655
9202
|
}
|
|
8656
9203
|
|
|
@@ -9954,6 +10501,19 @@ function main() {
|
|
|
9954
10501
|
const fakeEntries = allFiles.map(f => ({ filePath: f }));
|
|
9955
10502
|
coverageResult = coverageScore(cwd, fakeEntries, cfg);
|
|
9956
10503
|
} catch (_) {}
|
|
10504
|
+
// v6.7: Collect cache stats if enabled
|
|
10505
|
+
let cacheStats = null;
|
|
10506
|
+
try {
|
|
10507
|
+
const cachePath = path.join(cwd, '.sigmap-cache.json');
|
|
10508
|
+
if (fs.existsSync(cachePath)) {
|
|
10509
|
+
const raw = fs.readFileSync(cachePath, 'utf8');
|
|
10510
|
+
const data = JSON.parse(raw);
|
|
10511
|
+
const sizeKb = Math.round(Buffer.byteLength(raw) / 1024);
|
|
10512
|
+
const entries = Object.keys(data.entries || {}).length;
|
|
10513
|
+
const mtime = fs.statSync(cachePath).mtimeMs;
|
|
10514
|
+
cacheStats = { sizeKb, entries, mtimeMs: mtime };
|
|
10515
|
+
}
|
|
10516
|
+
} catch (_) {}
|
|
9957
10517
|
if (args.includes('--json')) {
|
|
9958
10518
|
// Feature 3 (VS Code) + Feature 5 (JetBrains): emit tokens + reduction for plugins
|
|
9959
10519
|
const ctxPath = path.join(cwd, '.github', 'copilot-instructions.md');
|
|
@@ -9970,6 +10530,9 @@ function main() {
|
|
|
9970
10530
|
payload.coverageTotalFiles = coverageResult.total;
|
|
9971
10531
|
payload.coverageIncludedFiles = coverageResult.included;
|
|
9972
10532
|
}
|
|
10533
|
+
if (cacheStats) {
|
|
10534
|
+
payload.cacheStats = cacheStats;
|
|
10535
|
+
}
|
|
9973
10536
|
process.stdout.write(JSON.stringify(payload) + '\n');
|
|
9974
10537
|
} else {
|
|
9975
10538
|
console.log('[sigmap] health:');
|
|
@@ -9983,6 +10546,9 @@ function main() {
|
|
|
9983
10546
|
if (result.strategyFreshnessDays !== null) {
|
|
9984
10547
|
console.log(` cold freshness : ${result.strategyFreshnessDays} day(s)`);
|
|
9985
10548
|
}
|
|
10549
|
+
if (cacheStats) {
|
|
10550
|
+
console.log(` sig-cache : ${cacheStats.entries} files cached ${cacheStats.sizeKb}KB on disk`);
|
|
10551
|
+
}
|
|
9986
10552
|
console.log(` total runs : ${result.totalRuns}`);
|
|
9987
10553
|
console.log(` over-budget runs: ${result.overBudgetRuns}`);
|
|
9988
10554
|
console.log(` p50 token count : ${result.p50TokenCount}`);
|
package/package.json
CHANGED