sigmap 8.5.0 → 8.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +29 -7
- package/gen-context.js +60 -7
- package/llms-full.txt +9 -7
- package/llms.txt +4 -4
- 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/verify/lib-index.js +29 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,17 @@ Format: [Semantic Versioning](https://semver.org/)
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
## [8.6.0] — 2026-07-05
|
|
14
|
+
|
|
15
|
+
Minor release — **Phase 1 "bank the A": the grounding moat's supporting surface.** Three master-plan items land together: a self-contained, third-party-runnable benchmark harness (G1), installed dependency version pins in the generated context header (D8), and `verify` promoted to a documented flagship command (G2). All zero-dependency, deterministic, and in-boundary.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- **Public benchmark harness (#425, PR #426):** new `public-benchmarks/` — a self-contained, third-party-runnable retrieval harness. `repos.csv` (18 real repos pinned to exact commits), `queries.json` (90 natural-language query → expected-file tasks), `run.sh` (shallow-clones the pinned repos, then scores), `score.mjs` (maps each repo with `gen-context.js`, ranks with the **shipped** identifier-aware BM25 ranker `src/retrieval/bm25.js`, reports hit@1/hit@5/MRR), and a methodology `README.md`. Deterministic — pinned commits + a byte-stable map + rank-only math → the same numbers on any machine; no LLM, no API keys, no external deps. Dev-only (excluded from the npm package). Turns the published retrieval numbers from a claim into a third-party-verifiable fact (v9.0 G1).
|
|
19
|
+
- **Version pins in the context header (#425, PR #426):** the generated header now carries a `## versions (installed direct deps)` block of sorted `name@version` pins for installed JS + Python direct dependencies, so agents reading `CLAUDE.md`/`AGENTS.md` ground against what is **actually installed here** (compounds with the G5/D5 verify moat). New `collectVersionPins(cwd)` in `src/verify/lib-index.js` (versions only — no symbol parsing, cheap enough to run per-build); gated by a new `versionPins` config key (default on). Byte-stable given a fixed installed tree (D8).
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- **`sigmap verify` — the grounding flagship (#425, PR #426):** `verify` is now a first-class alias of `verify-ai-output` (identical flags, output, and exit codes), with a dedicated flagship section near the top of the README and a `--help` entry. Positions the deterministic grounding guard — the one capability no agentic-grep loop or competitor offers — as the headline (v9.0 G2).
|
|
23
|
+
|
|
13
24
|
## [8.5.0] — 2026-07-05
|
|
14
25
|
|
|
15
26
|
Minor release — **deterministic query expansion (a vocabulary-mismatch recall aid).** The BM25 ranker now bridges common code-domain synonyms/abbreviations so a query for `authentication` can still surface a file whose signatures only say `auth`. Zero-dependency, deterministic. **Honest framing:** measured on the retrieval benchmark, this is **benchmark-neutral** (hit@5 unchanged within the harness's 86.7–87.8% noise band at the shipped weight) — not a hit@5 improvement. The benefit is for real users whose query vocabulary differs from the code, a case the curated benchmark doesn't exercise.
|
package/README.md
CHANGED
|
@@ -52,15 +52,15 @@ That map is exactly what agentic grep is worst at: reproducible, auditable conte
|
|
|
52
52
|
|
|
53
53
|
**Deterministic and verifiable — the two things an agentic-grep loop can't give you:**
|
|
54
54
|
- **Deterministic** — no LLM calls, no agent loop; the same repo always produces a byte-identical map you can diff, cache, and gate in CI.
|
|
55
|
-
- **Auditable & grounded** — every file and symbol traces to a real line anchor; `sigmap verify
|
|
55
|
+
- **Auditable & grounded** — every file and symbol traces to a real line anchor; `sigmap verify` flags any AI claim that isn't.
|
|
56
56
|
- **Zero dependencies** — `npx sigmap` on any machine; no embeddings, no vector DB, no hosted service, fully offline.
|
|
57
57
|
|
|
58
58
|
**Proof it pays off** (full benchmark below):
|
|
59
59
|
<!--SM:whyMetrics-->
|
|
60
60
|
- **86.7% hit@5** — right file found in top 5 results (vs 13.6% baseline)
|
|
61
61
|
- **97.0% token reduction** — average across 21 real repos
|
|
62
|
-
- **
|
|
63
|
-
- **1.
|
|
62
|
+
- **66.7% task success rate** — up from 10% without context
|
|
63
|
+
- **1.47 prompts per task** — down from 2.84 (48.4% fewer retries)
|
|
64
64
|
<!--/SM:whyMetrics-->
|
|
65
65
|
- **<!--SM:languages-->33<!--/SM:languages--> languages supported** — TypeScript, Python, Go, Rust, Java, R, and more
|
|
66
66
|
- **No vendor lock-in** — works with any AI assistant or local LLM
|
|
@@ -69,6 +69,28 @@ That map is exactly what agentic grep is worst at: reproducible, auditable conte
|
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
+
## 🔒 `sigmap verify` — the grounding flagship
|
|
73
|
+
|
|
74
|
+
The one thing no agentic-grep loop, and no competitor, gives you: **prove an AI answer is anchored to real signatures and line numbers before you trust it.** Deterministic, offline, no LLM — SigMap indexes your repo *plus the libraries actually installed here* and flags every fabricated file, import, symbol, test, or npm script.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
sigmap verify answer.md # ✓ grounded, or a line-by-line list of fabrications
|
|
78
|
+
sigmap verify answer.md --json # machine-readable report; exits 1 if any issue (CI gate)
|
|
79
|
+
sigmap verify answer.md --report # standalone red/amber/green HTML report
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
[sigmap] ✗ answer.md — 2 issues found
|
|
84
|
+
fake-file: 1 fake-test-file: 0 fake-import: 0 fake-symbol: 1 fake-npm-script: 0
|
|
85
|
+
|
|
86
|
+
L12 [Fake file] src/auth/session-store.js does not exist
|
|
87
|
+
L27 [Fake symbol] authorize() — did you mean authenticate()?
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`verify` is the flagship; `verify-ai-output` remains as the full command name. Pair it with `sigmap verify-plan` (check a plan before execution) and the `verify_suggestion` MCP tool (verify AI code against repo + private + installed-library symbols mid-session).
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
72
94
|
## Replace this with SigMap
|
|
73
95
|
|
|
74
96
|
| Without SigMap | With SigMap |
|
|
@@ -98,13 +120,13 @@ Ask → Rank → Context → Validate → Judge → Learn
|
|
|
98
120
|
|
|
99
121
|
<!--SM:benchmarkBlock-->
|
|
100
122
|
```
|
|
101
|
-
Benchmark : sigmap-v8.
|
|
102
|
-
Date : 2026-07-
|
|
123
|
+
Benchmark : sigmap-v8.6-main (21 repositories, including R language)
|
|
124
|
+
Date : 2026-07-05
|
|
103
125
|
|
|
104
126
|
Hit@5 : 86.7% (baseline 13.6% — 6.4× lift)
|
|
105
127
|
Token reduction: 97.0% (across 21 repos)
|
|
106
|
-
Prompt reduction : 48.
|
|
107
|
-
Task success :
|
|
128
|
+
Prompt reduction : 48.4% (2.84 → 1.47 prompts per task)
|
|
129
|
+
Task success : 66.7% (baseline 10%)
|
|
108
130
|
Repos tested : 21 (JavaScript, Python, Go, Rust, Java, R, C++, C#, Dart, Swift, Ruby, PHP, Scala, Kotlin, and more)
|
|
109
131
|
```
|
|
110
132
|
<!--/SM:benchmarkBlock-->
|
package/gen-context.js
CHANGED
|
@@ -1498,6 +1498,9 @@ __factories["./src/config/defaults"] = function(module, exports) {
|
|
|
1498
1498
|
// Include a compact import dependency map at top of output
|
|
1499
1499
|
depMap: true,
|
|
1500
1500
|
|
|
1501
|
+
// Include a compact `name@version` list of installed direct deps (D8)
|
|
1502
|
+
versionPins: true,
|
|
1503
|
+
|
|
1501
1504
|
// Include TODO/FIXME/HACK/XXX comments as compact section
|
|
1502
1505
|
todos: true,
|
|
1503
1506
|
|
|
@@ -13108,7 +13111,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
|
|
|
13108
13111
|
|
|
13109
13112
|
const SERVER_INFO = {
|
|
13110
13113
|
name: 'sigmap',
|
|
13111
|
-
version: '8.
|
|
13114
|
+
version: '8.6.0',
|
|
13112
13115
|
description: 'SigMap MCP server — code signatures on demand',
|
|
13113
13116
|
};
|
|
13114
13117
|
|
|
@@ -17311,8 +17314,37 @@ __factories["./src/verify/lib-index"] = function(module, exports) {
|
|
|
17311
17314
|
.map((l) => `${l.name}@${l.version}`);
|
|
17312
17315
|
}
|
|
17313
17316
|
|
|
17317
|
+
/**
|
|
17318
|
+
* D8: collect `name@version` pins for direct dependencies — versions only, no
|
|
17319
|
+
* symbol extraction, no cache. Cheap enough to run on every context build so
|
|
17320
|
+
* the generated header can ground against what is actually installed (JS +
|
|
17321
|
+
* Python). Deterministic: sorted, then capped.
|
|
17322
|
+
* @param {string} cwd
|
|
17323
|
+
* @param {object} [opts]
|
|
17324
|
+
* @param {number} [opts.limit=40] max pins returned (after sort)
|
|
17325
|
+
* @returns {{ pins: string[], total: number }} pins capped to limit; total = all resolved
|
|
17326
|
+
*/
|
|
17327
|
+
function collectVersionPins(cwd, opts = {}) {
|
|
17328
|
+
const limit = Number.isInteger(opts.limit) && opts.limit >= 0 ? opts.limit : 40;
|
|
17329
|
+
const pins = [];
|
|
17330
|
+
for (const dep of directDeps(cwd).slice(0, MAX_DEPS)) {
|
|
17331
|
+
const r = resolveEntry(cwd, dep);
|
|
17332
|
+
if (r && r.version) pins.push(`${dep}@${r.version}`);
|
|
17333
|
+
}
|
|
17334
|
+
const sitePkgs = findSitePackages(cwd);
|
|
17335
|
+
if (sitePkgs.length) {
|
|
17336
|
+
for (const dep of pythonDirectDeps(cwd).slice(0, MAX_DEPS)) {
|
|
17337
|
+
const r = resolvePyEntry(sitePkgs, dep);
|
|
17338
|
+
if (r && r.version) pins.push(`${dep}@${r.version}`);
|
|
17339
|
+
}
|
|
17340
|
+
}
|
|
17341
|
+
pins.sort();
|
|
17342
|
+
return { pins: limit ? pins.slice(0, limit) : pins, total: pins.length };
|
|
17343
|
+
}
|
|
17344
|
+
|
|
17314
17345
|
module.exports = {
|
|
17315
17346
|
buildLibraryIndex, extractDtsExports, directDeps, resolveEntry, formatVersionPins,
|
|
17347
|
+
collectVersionPins,
|
|
17316
17348
|
extractPyExports, pythonDirectDeps, findSitePackages, resolvePyEntry,
|
|
17317
17349
|
};
|
|
17318
17350
|
|
|
@@ -17647,7 +17679,7 @@ function __tryGit(args, opts = {}) {
|
|
|
17647
17679
|
catch (_) { return ''; }
|
|
17648
17680
|
}
|
|
17649
17681
|
|
|
17650
|
-
const VERSION = '8.
|
|
17682
|
+
const VERSION = '8.6.0';
|
|
17651
17683
|
const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
|
|
17652
17684
|
|
|
17653
17685
|
function requireSourceOrBundled(key) {
|
|
@@ -18250,6 +18282,23 @@ function formatOutput(fileEntries, cwd, routingEnabled, config, extras) {
|
|
|
18250
18282
|
lines.push('');
|
|
18251
18283
|
}
|
|
18252
18284
|
|
|
18285
|
+
// D8: installed direct-dependency version pins — grounds agents against what
|
|
18286
|
+
// is actually installed here (byte-stable given a fixed installed tree).
|
|
18287
|
+
if (!config || config.versionPins !== false) {
|
|
18288
|
+
try {
|
|
18289
|
+
const { collectVersionPins } = requireSourceOrBundled('./src/verify/lib-index');
|
|
18290
|
+
const { pins, total } = collectVersionPins(cwd);
|
|
18291
|
+
if (pins.length) {
|
|
18292
|
+
lines.push('## versions (installed direct deps)');
|
|
18293
|
+
lines.push('```');
|
|
18294
|
+
lines.push(...pins);
|
|
18295
|
+
if (total > pins.length) lines.push(`… +${total - pins.length} more`);
|
|
18296
|
+
lines.push('```');
|
|
18297
|
+
lines.push('');
|
|
18298
|
+
}
|
|
18299
|
+
} catch (_) { /* no/uninstalled deps → skip */ }
|
|
18300
|
+
}
|
|
18301
|
+
|
|
18253
18302
|
const todoLines = buildTodoSection(fileEntries, cwd, config || {});
|
|
18254
18303
|
if (todoLines.length) {
|
|
18255
18304
|
lines.push('## todos');
|
|
@@ -19442,9 +19491,10 @@ Usage:
|
|
|
19442
19491
|
${cmd} --impact <file> Show every file impacted by changing <file>
|
|
19443
19492
|
${cmd} --impact <file> --json Impact as JSON {changed, direct, transitive, tests, routes}
|
|
19444
19493
|
${cmd} --impact <file> --depth <n> BFS depth limit (default 3, 0=unlimited)
|
|
19445
|
-
${cmd} verify
|
|
19446
|
-
${cmd} verify
|
|
19447
|
-
${cmd} verify
|
|
19494
|
+
${cmd} verify <answer.md> Flagship grounding guard — flag fake files/tests/imports/symbols/npm-scripts in an AI answer (alias of verify-ai-output)
|
|
19495
|
+
${cmd} verify <answer.md> --json Grounding report as JSON (exits 1 if issues)
|
|
19496
|
+
${cmd} verify <answer.md> --report Write a standalone HTML report (red/amber/green)
|
|
19497
|
+
${cmd} verify-ai-output <answer.md> Full command name for ${cmd} verify
|
|
19448
19498
|
${cmd} conventions Extract repo file-naming/export/test conventions (--conflicts, --inject, --report, --fix)
|
|
19449
19499
|
${cmd} scaffold "<name>" Propose a convention-matched file/dir scaffold (--ext, --threshold, --force, --json)
|
|
19450
19500
|
${cmd} verify-plan <plan.md|-> Check a plan vs the live index — files/symbols exist, blast radius, scope (--json)
|
|
@@ -21304,7 +21354,10 @@ function main() {
|
|
|
21304
21354
|
process.exit(s.ok ? 0 : 1);
|
|
21305
21355
|
}
|
|
21306
21356
|
|
|
21307
|
-
|
|
21357
|
+
// `sigmap verify` is the flagship alias for `verify-ai-output` — the grounding
|
|
21358
|
+
// guard that proves an AI answer is anchored to real signatures + line anchors.
|
|
21359
|
+
if (args[0] === 'verify-ai-output' || args[0] === 'verify') {
|
|
21360
|
+
const cmdName = args[0];
|
|
21308
21361
|
const target = args[1];
|
|
21309
21362
|
const jsonOut = args.includes('--json');
|
|
21310
21363
|
const reportIdx = args.indexOf('--report');
|
|
@@ -21312,7 +21365,7 @@ function main() {
|
|
|
21312
21365
|
? (args[reportIdx + 1] && !args[reportIdx + 1].startsWith('--') ? args[reportIdx + 1] : 'sigmap-verify-report.html')
|
|
21313
21366
|
: null;
|
|
21314
21367
|
if (!target || target.startsWith('--')) {
|
|
21315
|
-
console.error(
|
|
21368
|
+
console.error(`[sigmap] Usage: sigmap ${cmdName} <answer.md> [--json] [--report [out.html]]`);
|
|
21316
21369
|
process.exit(1);
|
|
21317
21370
|
}
|
|
21318
21371
|
const absTarget = path.resolve(cwd, target);
|
package/llms-full.txt
CHANGED
|
@@ -11,20 +11,20 @@ ranking keeps the relevant context in scope (cutting tokens ~97% as a side
|
|
|
11
11
|
effect), with no LLM calls, embeddings, or vector database. Works with Claude,
|
|
12
12
|
Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
|
|
13
13
|
|
|
14
|
-
# Version: 8.
|
|
14
|
+
# Version: 8.6.0 | Benchmark: sigmap-v8.6-main (2026-07-05)
|
|
15
15
|
# Source: auto-generated from package.json, version.json, benchmarks/latest.json, src/mcp/tools.js, src/config/defaults.js
|
|
16
16
|
# Regenerate: npm run generate:llms | Validate: npm run validate:llms
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
## Core metrics (benchmark: sigmap-v8.
|
|
20
|
+
## Core metrics (benchmark: sigmap-v8.6-main, 2026-07-05)
|
|
21
21
|
|
|
22
22
|
| Metric | Without SigMap | With SigMap |
|
|
23
23
|
|--------|----------------|-------------|
|
|
24
24
|
| Retrieval hit@5 | 13.6% (random) | 86.7% (6.4× lift) |
|
|
25
25
|
| Token reduction | — | 97.0% average |
|
|
26
|
-
| Task success proxy | 10% |
|
|
27
|
-
| Prompts per task | 2.84 | 1.
|
|
26
|
+
| Task success proxy | 10% | 66.7% |
|
|
27
|
+
| Prompts per task | 2.84 | 1.47 (48.4% fewer) |
|
|
28
28
|
| Supported languages | — | 33 |
|
|
29
29
|
| MCP tools | — | 18 |
|
|
30
30
|
| npm runtime dependencies | — | 0 |
|
|
@@ -99,9 +99,10 @@ sigmap weights --json Learned weights as JSON
|
|
|
99
99
|
sigmap --impact <file> Show every file impacted by changing <file>
|
|
100
100
|
sigmap --impact <file> --json Impact as JSON {changed, direct, transitive, tests, routes}
|
|
101
101
|
sigmap --impact <file> --depth <n> BFS depth limit (default 3, 0=unlimited)
|
|
102
|
-
sigmap verify
|
|
103
|
-
sigmap verify
|
|
104
|
-
sigmap verify
|
|
102
|
+
sigmap verify <answer.md> Flagship grounding guard — flag fake files/tests/imports/symbols/npm-scripts in an AI answer (alias of verify-ai-output)
|
|
103
|
+
sigmap verify <answer.md> --json Grounding report as JSON (exits 1 if issues)
|
|
104
|
+
sigmap verify <answer.md> --report Write a standalone HTML report (red/amber/green)
|
|
105
|
+
sigmap verify-ai-output <answer.md> Full command name for gen-context verify
|
|
105
106
|
sigmap conventions Extract repo file-naming/export/test conventions (--conflicts, --inject, --report, --fix)
|
|
106
107
|
sigmap scaffold "<name>" Propose a convention-matched file/dir scaffold (--ext, --threshold, --force, --json)
|
|
107
108
|
sigmap verify-plan <plan.md|-> Check a plan vs the live index — files/symbols exist, blast radius, scope (--json)
|
|
@@ -310,6 +311,7 @@ format = default
|
|
|
310
311
|
tracking = false
|
|
311
312
|
mcp = {"autoRegister":true}
|
|
312
313
|
depMap = true
|
|
314
|
+
versionPins = true
|
|
313
315
|
todos = true
|
|
314
316
|
changes = true
|
|
315
317
|
changesCommits = 10
|
package/llms.txt
CHANGED
|
@@ -11,7 +11,7 @@ ranking keeps the relevant context in scope (cutting tokens ~97% as a side
|
|
|
11
11
|
effect), with no LLM calls, embeddings, or vector database. Works with Claude,
|
|
12
12
|
Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
|
|
13
13
|
|
|
14
|
-
# Version: 8.
|
|
14
|
+
# Version: 8.6.0 | Benchmark: sigmap-v8.6-main (2026-07-05)
|
|
15
15
|
# Source: auto-generated from package.json, version.json, benchmarks/latest.json, src/mcp/tools.js, src/config/defaults.js
|
|
16
16
|
# Regenerate: npm run generate:llms | Validate: npm run validate:llms
|
|
17
17
|
|
|
@@ -23,12 +23,12 @@ Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
|
|
|
23
23
|
- No blast-radius awareness before editing a hub file — `--impact` shows every file a change touches.
|
|
24
24
|
- Pasted stack traces, CI logs, and JSON bloat the prompt — `squeeze` minimizes them and enriches the top frame from the symbol index.
|
|
25
25
|
|
|
26
|
-
## Core metrics (benchmark: sigmap-v8.
|
|
26
|
+
## Core metrics (benchmark: sigmap-v8.6-main, 2026-07-05)
|
|
27
27
|
|
|
28
28
|
- hit@5 retrieval: 86.7% vs 13.6% random baseline (6.4× lift)
|
|
29
29
|
- Token reduction: 97.0% average across benchmark repos
|
|
30
|
-
- Task success:
|
|
31
|
-
- Prompts per task: 1.
|
|
30
|
+
- Task success: 66.7% vs 10% without SigMap
|
|
31
|
+
- Prompts per task: 1.47 vs 2.84 baseline (48.4% fewer)
|
|
32
32
|
- Languages: 33 supported · MCP tools: 18
|
|
33
33
|
- Dependencies: zero npm runtime dependencies · fully offline
|
|
34
34
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sigmap",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.6.0",
|
|
4
4
|
"description": "97% token reduction for AI coding. Extracts function & class signatures with TF-IDF ranking to feed only the right files to Claude, Cursor, Copilot, Aider, Windsurf, local LLMs & MCP. Zero dependencies, runs offline via npx.",
|
|
5
5
|
"main": "packages/core/index.js",
|
|
6
6
|
"exports": {
|
package/src/config/defaults.js
CHANGED
|
@@ -114,6 +114,9 @@ const DEFAULTS = {
|
|
|
114
114
|
// Include a compact import dependency map at top of output
|
|
115
115
|
depMap: true,
|
|
116
116
|
|
|
117
|
+
// Include a compact `name@version` list of installed direct deps (D8)
|
|
118
|
+
versionPins: true,
|
|
119
|
+
|
|
117
120
|
// Include TODO/FIXME/HACK/XXX comments as compact section
|
|
118
121
|
todos: true,
|
|
119
122
|
|
package/src/mcp/server.js
CHANGED
package/src/verify/lib-index.js
CHANGED
|
@@ -298,7 +298,36 @@ function formatVersionPins(libraries) {
|
|
|
298
298
|
.map((l) => `${l.name}@${l.version}`);
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
/**
|
|
302
|
+
* D8: collect `name@version` pins for direct dependencies — versions only, no
|
|
303
|
+
* symbol extraction, no cache. Cheap enough to run on every context build so
|
|
304
|
+
* the generated header can ground against what is actually installed (JS +
|
|
305
|
+
* Python). Deterministic: sorted, then capped.
|
|
306
|
+
* @param {string} cwd
|
|
307
|
+
* @param {object} [opts]
|
|
308
|
+
* @param {number} [opts.limit=40] max pins returned (after sort)
|
|
309
|
+
* @returns {{ pins: string[], total: number }} pins capped to limit; total = all resolved
|
|
310
|
+
*/
|
|
311
|
+
function collectVersionPins(cwd, opts = {}) {
|
|
312
|
+
const limit = Number.isInteger(opts.limit) && opts.limit >= 0 ? opts.limit : 40;
|
|
313
|
+
const pins = [];
|
|
314
|
+
for (const dep of directDeps(cwd).slice(0, MAX_DEPS)) {
|
|
315
|
+
const r = resolveEntry(cwd, dep);
|
|
316
|
+
if (r && r.version) pins.push(`${dep}@${r.version}`);
|
|
317
|
+
}
|
|
318
|
+
const sitePkgs = findSitePackages(cwd);
|
|
319
|
+
if (sitePkgs.length) {
|
|
320
|
+
for (const dep of pythonDirectDeps(cwd).slice(0, MAX_DEPS)) {
|
|
321
|
+
const r = resolvePyEntry(sitePkgs, dep);
|
|
322
|
+
if (r && r.version) pins.push(`${dep}@${r.version}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
pins.sort();
|
|
326
|
+
return { pins: limit ? pins.slice(0, limit) : pins, total: pins.length };
|
|
327
|
+
}
|
|
328
|
+
|
|
301
329
|
module.exports = {
|
|
302
330
|
buildLibraryIndex, extractDtsExports, directDeps, resolveEntry, formatVersionPins,
|
|
331
|
+
collectVersionPins,
|
|
303
332
|
extractPyExports, pythonDirectDeps, findSitePackages, resolvePyEntry,
|
|
304
333
|
};
|