@hasna/skills 0.10.71 → 0.10.72

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/dist/storage.js CHANGED
@@ -53,13 +53,13 @@ import {
53
53
  mkdirSync as mkdirSync3,
54
54
  readFileSync as readFileSync3,
55
55
  readdirSync,
56
- statSync,
56
+ statSync as statSync2,
57
57
  writeFileSync as writeFileSync3
58
58
  } from "fs";
59
59
  import { dirname as dirname2, join as join4, normalize, relative, sep } from "path";
60
60
 
61
61
  // src/lib/config.ts
62
- import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync } from "fs";
62
+ import { closeSync, constants, existsSync as existsSync2, fstatSync, lstatSync, openSync, readFileSync, statSync, writeFileSync, mkdirSync } from "fs";
63
63
  import { join as join2, dirname } from "path";
64
64
 
65
65
  // src/lib/retired-settings.ts
@@ -195,7 +195,8 @@ function skillsDataRootForHome(home) {
195
195
  var ENUM_KEYS = {
196
196
  defaultAgent: ["claude", "codex", "gemini", "pi", "opencode", "all"],
197
197
  defaultScope: ["global", "project"],
198
- format: ["compact", "json", "csv"]
198
+ format: ["compact", "json", "csv"],
199
+ sessionPinMigration: ["auto", "off"]
199
200
  };
200
201
  var STRING_KEYS = ["extensionsDir"];
201
202
  function validKeys() {
@@ -266,6 +267,9 @@ function saveConfig(key, value, scope = "project") {
266
267
  if (!validKeys().includes(key)) {
267
268
  throw new Error(`Unknown config key: ${key}. Valid keys: ${validKeys().join(", ")}`);
268
269
  }
270
+ if (key === "sessionPinMigration" && scope !== "global") {
271
+ throw new Error(`${key} is read only from the global configuration. Use: skills config set ${key} <auto|off> --global`);
272
+ }
269
273
  const normalized = normalizeConfigValue(key, value);
270
274
  if (normalized === undefined) {
271
275
  const allowed = allowedValues(key);
@@ -959,7 +963,7 @@ function walkFiles(dir) {
959
963
  const files = [];
960
964
  for (const entry of readdirSync(dir)) {
961
965
  const full = join4(dir, entry);
962
- const stats = statSync(full);
966
+ const stats = statSync2(full);
963
967
  if (stats.isDirectory())
964
968
  files.push(...walkFiles(full));
965
969
  else
@@ -330,9 +330,23 @@ What the software currently enforces is narrower:
330
330
  managed row's `installPath` to be `cache/<marketplace>/<plugin>/<version>`,
331
331
  checks every file in every retained cache version against the admission
332
332
  receipts without the review listing them, and binds unmanaged rows exactly.
333
+ - Claude rewrites the 13-digit millisecond timestamp in
334
+ `.claude/plugins/cache/<marketplace>/<plugin>/<version>/.orphaned_at` when it
335
+ starts. Capturing that exact path with `captureDiscoveryByteSources` or
336
+ `captureDiscoveryPathSources` (including the installer `path-bytes`
337
+ operation) produces a `claude-plugin-orphaned-at-v1` witness, and a fresh
338
+ explicit review converts a plain byte or `path-bytes` witness of it to that
339
+ form. The witness binds the marker's presence or absence, not its bytes or
340
+ inode. Every capture and check still requires a regular, non-symlink file
341
+ owned by the current user, at most 32 bytes, matching `^[1-9][0-9]{12}$`.
342
+ The name stays in `directories` membership, so other added or removed names
343
+ are still detected. A marker at any other depth, any other name, and any
344
+ Skills-owned producer tree keep their exact byte witnesses. A stored review
345
+ that binds the marker's bytes keeps that meaning and needs one fresh review.
333
346
  - An entirely absent retired Claude version root exempts only its plain byte
334
347
  sources (`hashMode` omitted or `"bytes"`, with no `format`, `fields` or
335
- `managedPlugins`). Such a source with a non-null `sha256` is also the only
348
+ `managedPlugins`) and a present `claude-plugin-orphaned-at-v1` marker. Such a
349
+ source with a non-null `sha256` is also the only
336
350
  thing that identifies the root, and the root qualifies only while it stays
337
351
  entirely absent and the reviewed settings and registry select a different,
338
352
  verified version. Every other source under that root is re-hashed as usual,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/skills",
3
- "version": "0.10.71",
3
+ "version": "0.10.72",
4
4
  "description": "Skills library for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {