@ataraxy-labs/sem 0.5.4 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,7 +24,7 @@
24
24
  <img src="https://img.shields.io/badge/rust-stable-orange" alt="Rust">
25
25
  <img src="https://img.shields.io/badge/tests-133_passing-brightgreen" alt="Tests">
26
26
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-yellow" alt="License"></a>
27
- <img src="https://img.shields.io/badge/languages-26-blue" alt="Languages">
27
+ <img src="https://img.shields.io/badge/languages-28-blue" alt="Languages">
28
28
  </p>
29
29
 
30
30
  sem is a semantic version control tool that works on top of Git. It parses your code with tree-sitter, extracts every function, class, and method as an entity, and diffs at the entity level instead of lines. This means you see "function `blahh` was modified" instead of "lines x-y changed."
@@ -92,6 +92,8 @@ If you installed via npm/bun, the binary lives in `node_modules/.bin/sem` and is
92
92
 
93
93
  Works in any Git repo. No setup required. Also works outside Git for arbitrary file comparison.
94
94
 
95
+ sem stores its SQLite entity cache outside the repository, under the OS cache directory by default. Set `SEM_CACHE_DIR=/path/to/cache` to override the cache root; repo-local overrides are ignored so cache files do not dirty the working tree.
96
+
95
97
  ### sem diff
96
98
 
97
99
  Entity-level diff with rename detection, structural hashing, and word-level inline highlights.
@@ -154,6 +156,9 @@ sem impact authenticateUser --json
154
156
 
155
157
  # Disambiguate by file
156
158
  sem impact authenticateUser --file src/auth.ts
159
+
160
+ # Include generated/build directories that repo-wide scans skip by default
161
+ sem impact authenticateUser --no-default-excludes
157
162
  ```
158
163
 
159
164
  ### sem blame
@@ -198,11 +203,15 @@ sem entities src/auth.ts
198
203
  # JSON output
199
204
  sem entities --json
200
205
  sem entities src/auth.ts --json
206
+
207
+ # Include generated/build directories that repo-wide scans skip by default
208
+ sem entities --no-default-excludes
201
209
  ```
202
210
 
203
211
  ### sem context
204
212
 
205
- Token-budgeted context for LLMs: the entity, its dependencies, and its dependents, fitted to a token budget.
213
+ Token-budgeted context for LLMs: the entity, its dependencies, and its dependents, fitted to a strict content token budget.
214
+ When the target signature itself does not fit, JSON output reports `target_omitted: true`.
206
215
 
207
216
  ```bash
208
217
  sem context authenticateUser
@@ -212,6 +221,9 @@ sem context authenticateUser --budget 4000
212
221
 
213
222
  # JSON output
214
223
  sem context authenticateUser --json
224
+
225
+ # Include generated/build directories that repo-wide scans skip by default
226
+ sem context authenticateUser --no-default-excludes
215
227
  ```
216
228
 
217
229
  ## Use as default Git diff
@@ -232,7 +244,7 @@ sem unsetup
232
244
 
233
245
  ## What it parses
234
246
 
235
- 26 programming languages with full entity extraction via tree-sitter:
247
+ 28 programming languages with full entity extraction via tree-sitter:
236
248
 
237
249
  | Language | Extensions | Entities |
238
250
  |----------|-----------|----------|
@@ -261,6 +273,8 @@ sem unsetup
261
273
  | Dart | `.dart` | classes, mixins, extensions, enums, type aliases, functions |
262
274
  | OCaml | `.ml` `.mli` | values, modules, types, classes, externals |
263
275
  | Scala | `.scala` `.sc` `.sbt` | classes, objects, traits, enums, functions, vals, extensions |
276
+ | Nix | `.nix` | bindings, inherit declarations |
277
+ | Haskell | `.hs` | functions, signatures, data types, newtypes, classes, instances, type synonyms |
264
278
  | Zig | `.zig` | functions, tests, variables |
265
279
 
266
280
  Plus structured data formats:
@@ -333,6 +347,11 @@ sem diff --format json
333
347
  "added": 1,
334
348
  "modified": 1,
335
349
  "deleted": 1,
350
+ "moved": 0,
351
+ "renamed": 0,
352
+ "reordered": 0,
353
+ "binary": 0,
354
+ "orphan": 0,
336
355
  "total": 3
337
356
  },
338
357
  "changes": [
@@ -341,12 +360,19 @@ sem diff --format json
341
360
  "changeType": "added",
342
361
  "entityType": "function",
343
362
  "entityName": "validateToken",
363
+ "startLine": 12,
364
+ "endLine": 18,
365
+ "oldStartLine": null,
366
+ "oldEndLine": null,
344
367
  "filePath": "src/auth.ts"
345
368
  }
346
- ]
369
+ ],
370
+ "binaryChanges": []
347
371
  }
348
372
  ```
349
373
 
374
+ The named change-type buckets (`added`, `modified`, `deleted`, `moved`, `renamed`, `reordered`) always sum to `total`. `orphan` is a cross-cutting metadata count for module-level changes, and those changes are already included in the named change-type buckets.
375
+
350
376
  ## As a library
351
377
 
352
378
  sem-core can be used as a Rust library dependency:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ataraxy-labs/sem",
3
- "version": "0.5.4",
3
+ "version": "0.8.0",
4
4
  "description": "npm wrapper for the sem CLI. Downloads the matching release binary and exposes the sem command in node_modules/.bin.",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "type": "module",
@@ -42,6 +42,6 @@
42
42
  "scripts": {
43
43
  "postinstall": "node ./scripts/postinstall.mjs",
44
44
  "prepack": "node ./scripts/sync-package-version.mjs",
45
- "test": "node ./scripts/package-meta.test.mjs"
45
+ "test": "node --test"
46
46
  }
47
47
  }
@@ -38,9 +38,21 @@ async function downloadFile(url, destinationPath) {
38
38
  }
39
39
 
40
40
  function extractArchive(archivePath, outputDirectory) {
41
- const result = spawnSync('tar', ['-xzf', archivePath, '-C', outputDirectory], {
42
- stdio: 'pipe',
43
- });
41
+ const args = ['-xzf', archivePath, '-C', outputDirectory];
42
+ let result = spawnSync('tar', args, { stdio: 'pipe' });
43
+
44
+ // On Windows, GNU tar (from Git for Windows / MSYS2) interprets colons in
45
+ // paths as remote host separators (host:path). If extraction fails with a
46
+ // colon-related error, retry with --force-local which disables this behavior.
47
+ // We don't add it unconditionally because the Windows built-in bsdtar doesn't
48
+ // recognize the flag.
49
+ if (
50
+ process.platform === 'win32' &&
51
+ result.status !== 0 &&
52
+ result.stderr?.toString('utf8').includes('Cannot connect to')
53
+ ) {
54
+ result = spawnSync('tar', [...args, '--force-local'], { stdio: 'pipe' });
55
+ }
44
56
 
45
57
  if (result.error) {
46
58
  throw new Error(`Failed to extract archive: ${result.error.message}`);
@@ -5,19 +5,36 @@ import fs from 'node:fs/promises';
5
5
  * Downloads checksums.txt from the release, verifies the archive matches.
6
6
  * Returns silently on success, throws on mismatch or missing checksum.
7
7
  */
8
- export async function verifyChecksum(archivePath, archiveName, releaseBaseUrl) {
8
+ export async function verifyChecksum(
9
+ archivePath,
10
+ archiveName,
11
+ releaseBaseUrl,
12
+ { env = process.env, fetchFn = fetch } = {},
13
+ ) {
14
+ if (env.SEM_SKIP_CHECKSUM === '1') {
15
+ console.warn('Skipping checksum verification because SEM_SKIP_CHECKSUM=1.');
16
+ return;
17
+ }
18
+
9
19
  const checksumsUrl = `${releaseBaseUrl}/checksums.txt`;
10
20
 
11
- const response = await fetch(checksumsUrl, {
12
- headers: { 'user-agent': '@ataraxy-labs/sem npm installer' },
13
- redirect: 'follow',
14
- });
21
+ let response;
22
+ try {
23
+ response = await fetchFn(checksumsUrl, {
24
+ headers: { 'user-agent': '@ataraxy-labs/sem npm installer' },
25
+ redirect: 'follow',
26
+ });
27
+ } catch (error) {
28
+ throw new Error(
29
+ `Failed to fetch checksum metadata from ${checksumsUrl}: ${error.message}`,
30
+ );
31
+ }
15
32
 
16
33
  if (!response.ok) {
17
- console.warn(
18
- `Could not fetch checksums (${response.status}), skipping verification.`,
34
+ throw new Error(
35
+ `Failed to fetch checksum metadata from ${checksumsUrl}: ` +
36
+ `${response.status} ${response.statusText}`,
19
37
  );
20
- return;
21
38
  }
22
39
 
23
40
  const checksumsText = await response.text();
@@ -33,10 +50,9 @@ export async function verifyChecksum(archivePath, archiveName, releaseBaseUrl) {
33
50
  }
34
51
 
35
52
  if (!expectedHash) {
36
- console.warn(
37
- `No checksum found for ${archiveName} in checksums.txt, skipping verification.`,
53
+ throw new Error(
54
+ `No checksum found for ${archiveName} in checksum metadata from ${checksumsUrl}.`,
38
55
  );
39
- return;
40
56
  }
41
57
 
42
58
  const fileBuffer = await fs.readFile(archivePath);