@ai-dossier/cli 0.8.3 → 0.8.5

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
@@ -4,11 +4,13 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/@ai-dossier/cli)](https://www.npmjs.com/package/@ai-dossier/cli)
5
5
  [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-blue.svg)](https://github.com/imboard-ai/ai-dossier/blob/main/LICENSE)
6
6
 
7
- **Enforce cryptographic verification before executing dossiers.**
7
+ **Install, verify, and publish dossiers — portable, signed, versioned skills — for any LLM tool.**
8
+
9
+ A dossier is a skill with trust built in. This CLI is how you author them, verify their signatures, publish them to a registry, and install them as Claude Code skills (`install-skill` / `skill-export`).
8
10
 
9
11
  ## The Problem This Solves
10
12
 
11
- **Reality**: LLMs cannot be relied upon to enforce security checks automatically.
13
+ A plain skill is unsigned, unversioned, and locked to one tool — and **LLMs cannot be relied upon to enforce security checks automatically.**
12
14
 
13
15
  Even with MCP server installed and protocol documentation:
14
16
  - ❌ LLMs may skip verification
@@ -225,7 +227,7 @@ ai-dossier pull org/dossier-a org/dossier-b
225
227
  ai-dossier pull org/my-dossier --force
226
228
  ```
227
229
 
228
- Pulled dossiers are cached locally with checksum verification. Subsequent `pull` calls skip the download if the version is already cached (use `--force` to override).
230
+ Pulled dossiers are cached locally with checksum verification. Subsequent `pull` calls skip the download if the version is already cached (use `--force` to override). See [Cache and Version Resolution](#cache-and-version-resolution) for how versionless names are resolved and how to control freshness.
229
231
 
230
232
  ### Export
231
233
 
@@ -244,6 +246,112 @@ ai-dossier export org/my-dossier --stdout
244
246
 
245
247
  ---
246
248
 
249
+ ## Skills
250
+
251
+ A dossier is a skill with trust, versioning, and registry distribution added. These commands bridge the registry and Claude Code skills (`~/.claude/skills/`).
252
+
253
+ A **trigger skill** is a thin `SKILL.md` that fires on a phrase and invokes a versioned, signed dossier via `ai-dossier run <registry-path>`. You author and trigger it like any skill, but it gains signing, version pinning, and registry distribution.
254
+
255
+ ### `install-skill` — registry dossier → Claude Code skill
256
+
257
+ ```bash
258
+ # Install a published skill into ~/.claude/skills/
259
+ ai-dossier install-skill org/skills/my-skill
260
+
261
+ # List installed skills / force a fresh re-pull / remove one
262
+ ai-dossier install-skill --list
263
+ ai-dossier install-skill org/skills/my-skill --fresh --force
264
+ ai-dossier install-skill --remove my-skill
265
+ ```
266
+
267
+ Restart Claude Code (or start a new session) to pick up a newly installed skill. At run time the skill calls `ai-dossier run <registry-path>`, which fetches and verifies the dossier on demand — so you don't need to install the dossier separately.
268
+
269
+ ### `skill-export` — local skill → registry dossier
270
+
271
+ Publish a locally installed skill to the registry as a versioned, signed dossier so others can `install-skill` it:
272
+
273
+ ```bash
274
+ # Publish ~/.claude/skills/my-skill to the registry (minor version bump)
275
+ ai-dossier skill-export my-skill --namespace org/skills
276
+
277
+ # Pin an explicit version, add a changelog, verify the roundtrip
278
+ ai-dossier skill-export my-skill --version 2.0.0 --changelog "Add range support" --verify
279
+ ```
280
+
281
+ | Option | Effect |
282
+ |--------|--------|
283
+ | `--namespace <ns>` | Registry namespace (default: first org or username) |
284
+ | `--version <v>` / `--major` / `--no-bump` | Control the published version |
285
+ | `--changelog <msg>` | Changelog message for the release |
286
+ | `--verify` | Re-install after publish to confirm the roundtrip |
287
+
288
+ ---
289
+
290
+ ## Cache and Version Resolution
291
+
292
+ The CLI maintains a local cache at `~/.dossier/cache/`:
293
+
294
+ - **Content cache** — `~/.dossier/cache/<name>/<version>.ds.md` (the dossier bytes, content-addressable by version).
295
+ - **Resolution cache** — `~/.dossier/cache/.resolution/<name>.json` (which version a versionless name resolves to, with TTL).
296
+
297
+ ### How versionless names resolve
298
+
299
+ Pinned references (`org/my-dossier@1.2.3`) are content-addressable and never expire — they bypass the resolver entirely.
300
+
301
+ Versionless references (`org/my-dossier`) are resolved through a **TTL'd resolution cache**:
302
+
303
+ 1. If a recent resolution exists (within TTL) → reuse it (no registry call).
304
+ 2. Otherwise → call the registry, write the resolved version to the resolution cache, return it.
305
+ 3. If the registry is unreachable → fall back to the highest-semver cached version and print a loud stderr warning. If nothing is cached, fail with a clear error.
306
+
307
+ This applies to `ai-dossier run`, `ai-dossier create`, and `ai-dossier install-skill`.
308
+
309
+ ### Controlling freshness
310
+
311
+ | Flag | Effect |
312
+ |------|--------|
313
+ | (none) | Use cached resolution if newer than `cache.resolutionTtlSeconds` (default 300s). |
314
+ | `--max-age <seconds>` | Override TTL for this call. `0` forces a registry check. |
315
+ | `--fresh` | Skip the resolution cache and the content cache; fetch fresh from the registry. |
316
+ | `--pull` (`run` only) | Refresh the content cache (re-download) but still resolve via the resolver. |
317
+
318
+ ```bash
319
+ # Default: use cached resolution if within 300s
320
+ ai-dossier run org/my-dossier
321
+
322
+ # Force a registry re-check
323
+ ai-dossier run org/my-dossier --max-age 0
324
+
325
+ # Skip the entire cache for this call
326
+ ai-dossier run org/my-dossier --fresh
327
+ ```
328
+
329
+ Configure the default TTL:
330
+
331
+ ```bash
332
+ dossier config cache.resolutionTtlSeconds 600
333
+ ```
334
+
335
+ ### `cache` subcommand
336
+
337
+ ```bash
338
+ # Show all cached dossiers (content cache)
339
+ ai-dossier cache list
340
+ ai-dossier cache list --size --json
341
+
342
+ # Show cached versionless → version resolutions (with timestamps)
343
+ ai-dossier cache resolutions
344
+ ai-dossier cache resolutions --json
345
+
346
+ # Remove cached entries
347
+ ai-dossier cache clean <name> # all versions of a dossier
348
+ ai-dossier cache clean <name> --ver 1.2.0 # specific version
349
+ ai-dossier cache clean --older-than 30 # entries older than N days
350
+ ai-dossier cache clean --all # everything (prompts; use -y to skip)
351
+ ```
352
+
353
+ ---
354
+
247
355
  ## Multi-Registry Resolution
248
356
 
249
357
  The CLI queries all configured registries in parallel when resolving dossiers (e.g., `dossier get`, `dossier run`, `dossier pull`). This uses `Promise.allSettled()` so a single registry failure does not block results from other registries.
@@ -641,34 +749,20 @@ Exit 0 (safe) or 1 (unsafe)
641
749
 
642
750
  ---
643
751
 
644
- ## Limitations
645
-
646
- ### Current Limitations
647
-
648
- 1. **Signature Verification**: Basic implementation
649
- - Detects test signatures (invalid/fake)
650
- - Full minisign verification requires external tool
651
- - Future: Native minisign support
652
-
653
- 2. **Trusted Keys**: Not yet implemented
654
- - Future: Check against ~/.dossier/trusted-keys.txt
655
- - Future: Key management commands
752
+ ## Capabilities & Limitations
656
753
 
657
- 3. **Execution**: --run flag not implemented
658
- - Currently just verifies
659
- - Future: Execute if verification passes
754
+ ### What's implemented
660
755
 
661
- ### Why These Limitations Exist
756
+ - ✅ **Checksum verification** (SHA256) — catches any tampering with the dossier body
757
+ - ✅ **Signature verification** — Ed25519 (Minisign-compatible) and AWS KMS; signatures are validated, not just detected
758
+ - ✅ **Trusted keys** — verified against `~/.dossier/trusted-keys.txt`; manage with `ai-dossier keys`
759
+ - ✅ **Risk assessment** — declared risk level + destructive-operation analysis gate execution
760
+ - ✅ **Execution** — `ai-dossier run` verifies, then executes if checks pass
662
761
 
663
- **Current status**: MVP for verification enforcement
664
- **Focus**: Get checksum verification working reliably
665
- **Future**: Full signature verification, trust management, execution
762
+ ### Current limitations
666
763
 
667
- **But even with limitations**:
668
- - ✅ Checksum verification catches tampering
669
- - ✅ Signature presence detection works
670
- - ✅ Exit codes enable integration
671
- - ✅ Enforces security before LLM involvement
764
+ - Verification is a single integrity stage (checksum + signature) plus risk assessment — there is no multi-stage sandbox; the executing agent enforces runtime permissions.
765
+ - Trust is local: you decide which keys to trust. A valid signature from an untrusted key is reported as such, not auto-trusted.
672
766
 
673
767
  ---
674
768
 
@@ -682,7 +776,7 @@ Exit 0 (safe) or 1 (unsafe)
682
776
 
683
777
  ### v0.2.0
684
778
  - ✅ Multi-command CLI structure (`ai-dossier <command>`)
685
- - ✅ `dossier run` command with 5-stage verification pipeline
779
+ - ✅ `ai-dossier run` command with integrity verification (checksum + signature)
686
780
  - ✅ LLM auto-detection and execution integration
687
781
 
688
782
  ### v0.3.0
@@ -715,18 +809,18 @@ Exit 0 (safe) or 1 (unsafe)
715
809
  - ✅ Coverage thresholds enforcement
716
810
  - ✅ Documentation consistency fixes
717
811
 
718
- ### v0.8.0 (Current)
812
+ ### v0.8.x (Current)
719
813
  - ✅ Zod validation on MCP prompt handlers
720
814
  - ✅ Complete doc link audit and fix (30+ broken links)
721
- - ✅ Remove all "coming soon" stubs
722
- - ✅ Purge stale GitHub Packages / Node 18 references
723
- - ✅ Improved getting-started learning path
815
+ - ✅ Ed25519 + AWS KMS signature verification with trusted-keys
816
+ - ✅ `install-skill` / `skill-export` (Claude Code skill bridge)
817
+ - ✅ Execution tracing with verified checksum + signer metadata
818
+ - ✅ TTL-based version resolution for the content cache
724
819
 
725
820
  ### v1.0.0 (Stable)
726
- - ⏳ Complete signature verification
727
- - ⏳ Trust management UI
728
- - ⏳ Integration with major LLM tools
729
- - ⏳ Comprehensive documentation
821
+ - ⏳ Stable, frozen CLI surface and exit-code contract
822
+ - ⏳ Deeper integration with major LLM tools
823
+ - ⏳ Expanded registry/discovery features
730
824
 
731
825
  ---
732
826
 
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Versionless dossier name → resolved version mapping with TTL.
3
+ *
4
+ * Pinned versions (name@1.2.3) are content-addressable and never go stale.
5
+ * Versionless names (name) are the only thing that ages, so the TTL belongs
6
+ * on resolution, not on cached content bytes.
7
+ *
8
+ * Resolution cache lives at ~/.dossier/cache/.resolution/<name>.json, one
9
+ * tiny file per dossier with { resolved_version, resolved_at, source_registry }.
10
+ *
11
+ * On registry failure, falls back to the highest-semver version already in
12
+ * ~/.dossier/cache/<name>/ and prints a loud stderr warning so the staleness
13
+ * is never silent.
14
+ */
15
+ export declare const DEFAULT_RESOLUTION_TTL_SECONDS = 300;
16
+ export declare const CACHE_DIR: string;
17
+ export declare const RESOLUTION_DIR: string;
18
+ export interface ResolutionRecord {
19
+ resolved_version: string;
20
+ resolved_at: string;
21
+ source_registry?: string;
22
+ }
23
+ export type ResolutionSource = 'cache' | 'registry' | 'stale-cache';
24
+ export interface ResolvedVersion {
25
+ version: string;
26
+ source: ResolutionSource;
27
+ registry?: string;
28
+ /** Present only when source === 'stale-cache' — explains why we did not reach the registry. */
29
+ warning?: string;
30
+ }
31
+ export interface ResolveOptions {
32
+ /** Skip the resolution cache and force a registry call. */
33
+ fresh?: boolean;
34
+ /** Override the TTL for this call. 0 forces a registry call. */
35
+ maxAgeSeconds?: number;
36
+ }
37
+ /** Highest-semver version currently cached on disk for this name, or null. */
38
+ export declare function highestCachedSemver(dossierName: string): string | null;
39
+ /**
40
+ * Resolve a versionless dossier name to a concrete version.
41
+ *
42
+ * Flow:
43
+ * 1. If !fresh and a resolution file exists and is within TTL → return cached resolution.
44
+ * 2. Otherwise call the registry. On success → write resolution file → return.
45
+ * 3. On registry failure → fall back to highest-semver cached version with a
46
+ * loud stderr warning. If nothing is cached, rethrow.
47
+ *
48
+ * Callers should pass an already-stripped name (without @version suffix). For
49
+ * pinned versions, skip this resolver entirely.
50
+ */
51
+ export declare function resolveCachedVersion(dossierName: string, opts?: ResolveOptions): Promise<ResolvedVersion>;
52
+ /** Exposed for the `cache resolutions` subcommand. */
53
+ export declare function listResolutions(): Array<{
54
+ name: string;
55
+ record: ResolutionRecord;
56
+ }>;
57
+ /** Exposed for tests and the `cache clean` flow — remove all resolution files. */
58
+ export declare function clearResolutions(): void;
59
+ /**
60
+ * Path to a cached dossier's content file (without checking existence).
61
+ * Centralises the `<cache>/<name>/<version>.ds.md` layout used by
62
+ * run/create/install-skill/pull so layout changes happen in one place.
63
+ */
64
+ export declare function cachedContentPath(dossierName: string, version: string): string;
65
+ /**
66
+ * Return cached dossier content as a string, or null if not cached.
67
+ * Single source of truth for the `existsSync(contentFile) ? read : miss`
68
+ * block that previously lived in run.ts, create.ts, and install-skill.ts.
69
+ */
70
+ export declare function readCachedContent(dossierName: string, version: string): string | null;
71
+ /**
72
+ * Write a dossier's content + .meta.json to the cache.
73
+ *
74
+ * The .meta.json shape (`cached_at` + `version` + `source_registry`) is the
75
+ * one read by `cache list` / `cache clean` and was previously duplicated
76
+ * verbatim in run.ts, create.ts, install-skill.ts, and pull.ts.
77
+ *
78
+ * Best-effort by default (errors swallowed, matching create.ts/install-skill.ts).
79
+ * Pass `throwOnError: true` for callers that want to surface write failures
80
+ * (pull.ts wants this — a failed download cache write is a hard failure).
81
+ */
82
+ export declare function writeCachedContent(dossierName: string, version: string, content: string, sourceRegistry: string | undefined, opts?: {
83
+ throwOnError?: boolean;
84
+ }): void;
85
+ /**
86
+ * Parse a `--max-age <seconds>` CLI option into a number, or return undefined
87
+ * when unset. Throws when the value is provided but not a valid number.
88
+ * Used by run/create/install-skill which all expose the same flag.
89
+ */
90
+ export declare function parseMaxAgeOption(raw: string | undefined): number | undefined;
91
+ //# sourceMappingURL=cache-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-resolver.d.ts","sourceRoot":"","sources":["../src/cache-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,SAAS,QAA+C,CAAC;AACtE,eAAO,MAAM,cAAc,QAAsC,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,UAAU,GAAG,aAAa,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAwED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CActE;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,eAAe,CAAC,CAwF1B;AAED,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC,CA2BnF;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQrF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,IAAI,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACpC,IAAI,CAsBN;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAO7E"}
@@ -0,0 +1,331 @@
1
+ "use strict";
2
+ /**
3
+ * Versionless dossier name → resolved version mapping with TTL.
4
+ *
5
+ * Pinned versions (name@1.2.3) are content-addressable and never go stale.
6
+ * Versionless names (name) are the only thing that ages, so the TTL belongs
7
+ * on resolution, not on cached content bytes.
8
+ *
9
+ * Resolution cache lives at ~/.dossier/cache/.resolution/<name>.json, one
10
+ * tiny file per dossier with { resolved_version, resolved_at, source_registry }.
11
+ *
12
+ * On registry failure, falls back to the highest-semver version already in
13
+ * ~/.dossier/cache/<name>/ and prints a loud stderr warning so the staleness
14
+ * is never silent.
15
+ */
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.RESOLUTION_DIR = exports.CACHE_DIR = exports.DEFAULT_RESOLUTION_TTL_SECONDS = void 0;
21
+ exports.highestCachedSemver = highestCachedSemver;
22
+ exports.resolveCachedVersion = resolveCachedVersion;
23
+ exports.listResolutions = listResolutions;
24
+ exports.clearResolutions = clearResolutions;
25
+ exports.cachedContentPath = cachedContentPath;
26
+ exports.readCachedContent = readCachedContent;
27
+ exports.writeCachedContent = writeCachedContent;
28
+ exports.parseMaxAgeOption = parseMaxAgeOption;
29
+ const node_fs_1 = __importDefault(require("node:fs"));
30
+ const node_os_1 = __importDefault(require("node:os"));
31
+ const node_path_1 = __importDefault(require("node:path"));
32
+ const config_1 = require("./config");
33
+ const helpers_1 = require("./helpers");
34
+ const multi_registry_1 = require("./multi-registry");
35
+ exports.DEFAULT_RESOLUTION_TTL_SECONDS = 300;
36
+ exports.CACHE_DIR = node_path_1.default.join(node_os_1.default.homedir(), '.dossier', 'cache');
37
+ exports.RESOLUTION_DIR = node_path_1.default.join(exports.CACHE_DIR, '.resolution');
38
+ function resolutionFilePath(dossierName) {
39
+ const safeDir = (0, helpers_1.safeDossierPath)(exports.RESOLUTION_DIR, dossierName);
40
+ return `${safeDir}.json`;
41
+ }
42
+ function readResolution(dossierName) {
43
+ const file = resolutionFilePath(dossierName);
44
+ try {
45
+ if (!node_fs_1.default.existsSync(file))
46
+ return null;
47
+ const raw = node_fs_1.default.readFileSync(file, 'utf8');
48
+ const parsed = JSON.parse(raw);
49
+ if (!parsed.resolved_version || !parsed.resolved_at) {
50
+ if (process.env.DOSSIER_DEBUG) {
51
+ process.stderr.write(`[cache-resolver] resolution file ${file} missing required fields; ignoring\n`);
52
+ }
53
+ return null;
54
+ }
55
+ return parsed;
56
+ }
57
+ catch (err) {
58
+ // Corrupted resolution file — warn (always) and fall through to re-resolve.
59
+ // Silent fallback would hide a real corruption issue from operators.
60
+ process.stderr.write(`⚠️ Resolution cache file unreadable (${file}): ${err.message}. Re-resolving from registry.\n`);
61
+ return null;
62
+ }
63
+ }
64
+ function writeResolution(dossierName, record) {
65
+ const file = resolutionFilePath(dossierName);
66
+ const targetDir = node_path_1.default.dirname(file);
67
+ // Node's mkdir({recursive:true,mode}) only applies `mode` to the leaf directory it creates.
68
+ // For org-scoped names (org/sub/name) we must chmod each intermediate dir under
69
+ // RESOLUTION_DIR to 0o700 so resolution metadata never becomes world-readable.
70
+ node_fs_1.default.mkdirSync(targetDir, { recursive: true, mode: 0o700 });
71
+ let cursor = targetDir;
72
+ while (cursor.startsWith(exports.RESOLUTION_DIR) && cursor !== node_path_1.default.dirname(exports.RESOLUTION_DIR)) {
73
+ try {
74
+ node_fs_1.default.chmodSync(cursor, 0o700);
75
+ }
76
+ catch {
77
+ // best-effort; if chmod fails (e.g. not owner) we still proceed
78
+ }
79
+ if (cursor === exports.RESOLUTION_DIR)
80
+ break;
81
+ cursor = node_path_1.default.dirname(cursor);
82
+ }
83
+ // Defend against symlink swap: if a non-regular file (symlink, fifo, etc.) sits at
84
+ // the target path, refuse to write through it. lstat does not follow symlinks.
85
+ try {
86
+ const st = node_fs_1.default.lstatSync(file);
87
+ if (!st.isFile()) {
88
+ node_fs_1.default.unlinkSync(file);
89
+ }
90
+ }
91
+ catch {
92
+ // ENOENT — fine, fresh write
93
+ }
94
+ node_fs_1.default.writeFileSync(file, JSON.stringify(record, null, 2), { encoding: 'utf8', mode: 0o600 });
95
+ }
96
+ function compareSemver(a, b) {
97
+ const pa = a.split('.').map(Number);
98
+ const pb = b.split('.').map(Number);
99
+ for (let i = 0; i < 3; i++) {
100
+ const diff = (pa[i] || 0) - (pb[i] || 0);
101
+ if (diff !== 0)
102
+ return diff;
103
+ }
104
+ return 0;
105
+ }
106
+ /** Highest-semver version currently cached on disk for this name, or null. */
107
+ function highestCachedSemver(dossierName) {
108
+ try {
109
+ const dir = (0, helpers_1.safeDossierPath)(exports.CACHE_DIR, dossierName);
110
+ if (!node_fs_1.default.existsSync(dir))
111
+ return null;
112
+ const versions = node_fs_1.default
113
+ .readdirSync(dir)
114
+ .filter((f) => f.endsWith('.meta.json'))
115
+ .map((f) => f.replace('.meta.json', ''))
116
+ .filter((v) => node_fs_1.default.existsSync(node_path_1.default.join(dir, `${v}.ds.md`)))
117
+ .sort(compareSemver);
118
+ return versions.length > 0 ? versions[versions.length - 1] : null;
119
+ }
120
+ catch {
121
+ return null;
122
+ }
123
+ }
124
+ function getConfiguredTtlSeconds() {
125
+ const raw = (0, config_1.getConfig)('cache.resolutionTtlSeconds');
126
+ if (typeof raw === 'number' && Number.isFinite(raw) && raw >= 0)
127
+ return raw;
128
+ return exports.DEFAULT_RESOLUTION_TTL_SECONDS;
129
+ }
130
+ function formatAge(ageMs) {
131
+ const seconds = Math.round(ageMs / 1000);
132
+ if (seconds < 60)
133
+ return `${seconds}s ago`;
134
+ const minutes = Math.round(seconds / 60);
135
+ if (minutes < 60)
136
+ return `${minutes}m ago`;
137
+ const hours = Math.round(minutes / 60);
138
+ if (hours < 24)
139
+ return `${hours}h ago`;
140
+ const days = Math.round(hours / 24);
141
+ return `${days}d ago`;
142
+ }
143
+ /**
144
+ * Resolve a versionless dossier name to a concrete version.
145
+ *
146
+ * Flow:
147
+ * 1. If !fresh and a resolution file exists and is within TTL → return cached resolution.
148
+ * 2. Otherwise call the registry. On success → write resolution file → return.
149
+ * 3. On registry failure → fall back to highest-semver cached version with a
150
+ * loud stderr warning. If nothing is cached, rethrow.
151
+ *
152
+ * Callers should pass an already-stripped name (without @version suffix). For
153
+ * pinned versions, skip this resolver entirely.
154
+ */
155
+ async function resolveCachedVersion(dossierName, opts = {}) {
156
+ const ttl = opts.maxAgeSeconds ?? getConfiguredTtlSeconds();
157
+ if (!opts.fresh && ttl > 0) {
158
+ const cached = readResolution(dossierName);
159
+ if (cached) {
160
+ const ageMs = Date.now() - new Date(cached.resolved_at).getTime();
161
+ if (ageMs >= 0 && ageMs < ttl * 1000) {
162
+ if (process.env.DOSSIER_DEBUG) {
163
+ process.stderr.write(`[cache-resolver] '${dossierName}' served from resolution cache: ` +
164
+ `version=${cached.resolved_version}, age=${formatAge(ageMs)}, ttl=${ttl}s, registry=${cached.source_registry ?? 'unknown'}\n`);
165
+ }
166
+ return {
167
+ version: cached.resolved_version,
168
+ source: 'cache',
169
+ registry: cached.source_registry,
170
+ };
171
+ }
172
+ if (process.env.DOSSIER_DEBUG) {
173
+ process.stderr.write(`[cache-resolver] '${dossierName}' resolution cache expired (age=${formatAge(ageMs)}, ttl=${ttl}s); re-resolving\n`);
174
+ }
175
+ }
176
+ else if (process.env.DOSSIER_DEBUG) {
177
+ process.stderr.write(`[cache-resolver] '${dossierName}' has no resolution cache; calling registry\n`);
178
+ }
179
+ }
180
+ else if (process.env.DOSSIER_DEBUG) {
181
+ process.stderr.write(`[cache-resolver] '${dossierName}' bypassing resolution cache (fresh=${opts.fresh ?? false}, ttl=${ttl}s)\n`);
182
+ }
183
+ let registryError = null;
184
+ try {
185
+ const { result, errors } = await (0, multi_registry_1.multiRegistryGetDossier)(dossierName);
186
+ if (result?.version) {
187
+ writeResolution(dossierName, {
188
+ resolved_version: result.version,
189
+ resolved_at: new Date().toISOString(),
190
+ source_registry: result._registry,
191
+ });
192
+ if (process.env.DOSSIER_DEBUG) {
193
+ process.stderr.write(`[cache-resolver] '${dossierName}' resolved from registry '${result._registry}' to version ${result.version}\n`);
194
+ }
195
+ return { version: result.version, source: 'registry', registry: result._registry };
196
+ }
197
+ const message = errors.length > 0 ? errors.map((e) => e.error).join('; ') : 'no result';
198
+ registryError = new Error(message);
199
+ }
200
+ catch (err) {
201
+ registryError = err;
202
+ }
203
+ // Registry unreachable — try stale fallback.
204
+ const fallback = highestCachedSemver(dossierName);
205
+ const lastKnown = readResolution(dossierName);
206
+ if (fallback) {
207
+ const ageHint = lastKnown
208
+ ? ` (last successful check: ${formatAge(Date.now() - new Date(lastKnown.resolved_at).getTime())})`
209
+ : ' (no record of last successful check)';
210
+ const warning = `Registry unreachable — falling back to cached ${dossierName}@${fallback}${ageHint}.\n` +
211
+ ` Cause: ${registryError?.message ?? 'unknown'}\n` +
212
+ ` This may be stale. To force a fresh check once registry is reachable, re-run with --fresh ` +
213
+ `(or --max-age 0).`;
214
+ process.stderr.write(`⚠️ ${warning}\n`);
215
+ return {
216
+ version: fallback,
217
+ source: 'stale-cache',
218
+ registry: lastKnown?.source_registry,
219
+ warning,
220
+ };
221
+ }
222
+ throw new Error(`Failed to resolve ${dossierName}: registry unreachable and no cached version available.\n` +
223
+ ` Underlying error: ${registryError?.message ?? 'unknown'}\n` +
224
+ ` Try:\n` +
225
+ ` 1. Check network connectivity\n` +
226
+ ` 2. Verify registry is configured: dossier config --list-registries\n` +
227
+ ` 3. Pin a known-good version: dossier run ${dossierName}@<version>\n` +
228
+ ` 4. Re-run with --fresh once the registry is reachable.`);
229
+ }
230
+ /** Exposed for the `cache resolutions` subcommand. */
231
+ function listResolutions() {
232
+ if (!node_fs_1.default.existsSync(exports.RESOLUTION_DIR))
233
+ return [];
234
+ const entries = [];
235
+ function walk(dir, prefix) {
236
+ for (const entry of node_fs_1.default.readdirSync(dir, { withFileTypes: true })) {
237
+ const full = node_path_1.default.join(dir, entry.name);
238
+ if (entry.isDirectory()) {
239
+ walk(full, prefix ? `${prefix}/${entry.name}` : entry.name);
240
+ }
241
+ else if (entry.name.endsWith('.json')) {
242
+ try {
243
+ const record = JSON.parse(node_fs_1.default.readFileSync(full, 'utf8'));
244
+ if (record.resolved_version && record.resolved_at) {
245
+ const name = entry.name.replace(/\.json$/, '');
246
+ entries.push({ name: prefix ? `${prefix}/${name}` : name, record });
247
+ }
248
+ }
249
+ catch {
250
+ // skip invalid entries
251
+ }
252
+ }
253
+ }
254
+ }
255
+ walk(exports.RESOLUTION_DIR, '');
256
+ entries.sort((a, b) => a.name.localeCompare(b.name));
257
+ return entries;
258
+ }
259
+ /** Exposed for tests and the `cache clean` flow — remove all resolution files. */
260
+ function clearResolutions() {
261
+ if (node_fs_1.default.existsSync(exports.RESOLUTION_DIR)) {
262
+ node_fs_1.default.rmSync(exports.RESOLUTION_DIR, { recursive: true, force: true });
263
+ }
264
+ }
265
+ /**
266
+ * Path to a cached dossier's content file (without checking existence).
267
+ * Centralises the `<cache>/<name>/<version>.ds.md` layout used by
268
+ * run/create/install-skill/pull so layout changes happen in one place.
269
+ */
270
+ function cachedContentPath(dossierName, version) {
271
+ return node_path_1.default.join((0, helpers_1.safeDossierPath)(exports.CACHE_DIR, dossierName), `${version}.ds.md`);
272
+ }
273
+ /**
274
+ * Return cached dossier content as a string, or null if not cached.
275
+ * Single source of truth for the `existsSync(contentFile) ? read : miss`
276
+ * block that previously lived in run.ts, create.ts, and install-skill.ts.
277
+ */
278
+ function readCachedContent(dossierName, version) {
279
+ const file = cachedContentPath(dossierName, version);
280
+ if (!node_fs_1.default.existsSync(file))
281
+ return null;
282
+ try {
283
+ return node_fs_1.default.readFileSync(file, 'utf8');
284
+ }
285
+ catch {
286
+ return null;
287
+ }
288
+ }
289
+ /**
290
+ * Write a dossier's content + .meta.json to the cache.
291
+ *
292
+ * The .meta.json shape (`cached_at` + `version` + `source_registry`) is the
293
+ * one read by `cache list` / `cache clean` and was previously duplicated
294
+ * verbatim in run.ts, create.ts, install-skill.ts, and pull.ts.
295
+ *
296
+ * Best-effort by default (errors swallowed, matching create.ts/install-skill.ts).
297
+ * Pass `throwOnError: true` for callers that want to surface write failures
298
+ * (pull.ts wants this — a failed download cache write is a hard failure).
299
+ */
300
+ function writeCachedContent(dossierName, version, content, sourceRegistry, opts = {}) {
301
+ const dir = (0, helpers_1.safeDossierPath)(exports.CACHE_DIR, dossierName);
302
+ try {
303
+ node_fs_1.default.mkdirSync(dir, { recursive: true, mode: 0o700 });
304
+ node_fs_1.default.writeFileSync(node_path_1.default.join(dir, `${version}.ds.md`), content, 'utf8');
305
+ node_fs_1.default.writeFileSync(node_path_1.default.join(dir, `${version}.meta.json`), JSON.stringify({
306
+ cached_at: new Date().toISOString(),
307
+ version,
308
+ source_registry: sourceRegistry,
309
+ }, null, 2), 'utf8');
310
+ }
311
+ catch (err) {
312
+ if (opts.throwOnError)
313
+ throw err;
314
+ // best-effort: swallow (matches prior create.ts / install-skill.ts behaviour)
315
+ }
316
+ }
317
+ /**
318
+ * Parse a `--max-age <seconds>` CLI option into a number, or return undefined
319
+ * when unset. Throws when the value is provided but not a valid number.
320
+ * Used by run/create/install-skill which all expose the same flag.
321
+ */
322
+ function parseMaxAgeOption(raw) {
323
+ if (raw === undefined)
324
+ return undefined;
325
+ const n = Number(raw);
326
+ if (Number.isNaN(n)) {
327
+ throw new Error(`--max-age must be a number (got "${raw}")`);
328
+ }
329
+ return n;
330
+ }
331
+ //# sourceMappingURL=cache-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-resolver.js","sourceRoot":"","sources":["../src/cache-resolver.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/commands/cache.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwP3D"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/commands/cache.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgU3D"}