doc-freshness-checker 2.0.21 → 2.0.23

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
@@ -38,7 +38,7 @@ Validate documentation against your codebase to catch stale references before th
38
38
  - **Documentation formats:** Markdown (`.md`, `.markdown`), reStructuredText (`.rst`), AsciiDoc (`.adoc`, `.asciidoc`), plaintext (`.txt`).
39
39
  - **Source indexing for symbol validation:** JavaScript, TypeScript, Python, Go, Rust, Java.
40
40
  - **Code snippet validation:** verifies import paths resolve, imported symbols are exported, function call signatures still match example placeholders, and config object keys match type/interface definitions.
41
- - **Manifest parsing for version/dependency checks:** `package.json`, `requirements.txt`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `pom.xml`.
41
+ - **Manifest hints for version/dependency checks:** basic format-specific identifiers and versions from listed `package.json`, `requirements.txt`, `pyproject.toml`, `go.mod`, `Cargo.toml`, and `pom.xml` files.
42
42
  - In the general manifest candidate set, concrete versions take precedence over unpinned entries. Python package names retain their Python-specific source precedence. Among equally concrete candidates, the later configured manifest wins.
43
43
  - Cargo parses simple and inline-table entries in `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`, and `[workspace.dependencies]`. Workspace references resolve from matching workspace definitions across explicitly listed `Cargo.toml` files. Dependency subtables, dotted keys, and target-specific sections are not parsed.
44
44
  - **Reporters:** `console`, `json`, `markdown`, `enhanced`.
@@ -173,11 +173,13 @@ doc-freshness --score --incremental
173
173
  | --------------------- | ------------------------------------------------------------------------------------------------ |
174
174
  | `file-path` | Referenced files/directories exist |
175
175
  | `external-url` | External URLs are reachable (with caching and skip rules) |
176
- | `version` | Mentioned versions compared to parsed manifests |
176
+ | `version` | Mentioned versions compared to extracted manifest version hints |
177
177
  | `directory-structure` | Tree snippets align with actual structure |
178
178
  | `code-pattern` | Mentioned symbols exist in indexed source |
179
179
  | `code-snippet` | Import paths resolve, exported symbols exist, function signatures still match, config keys valid |
180
- | `dependency` | Mentioned packages exist in manifest dependencies |
180
+ | `dependency` | Mentioned packages exist among extracted manifest identifiers |
181
+
182
+ Extraction uses basic format-specific heuristics; it does not execute package managers or build backends, inspect generated metadata, discover workspace members, or implement full ecosystem grammars.
181
183
 
182
184
  ### URL Validation Behavior
183
185
 
@@ -1,15 +1,28 @@
1
1
  import { CodeDocGraph } from '../graph/codeDocGraph.js';
2
2
  import type { CacheStats2, DocFreshnessConfig, UrlCacheEntry } from '../types.js';
3
+ export type CachePolicy = Readonly<{
4
+ enabled: boolean;
5
+ dir: string;
6
+ }>;
3
7
  /**
4
- * Manages caching of graph and URL validation results
8
+ * Resolves result-cache policy and manages persisted cache data
5
9
  */
6
10
  export declare class CacheManager {
7
11
  private config;
8
- private cacheDir;
12
+ private rootDir;
13
+ private rawDir;
14
+ readonly policy: CachePolicy;
9
15
  private cacheFile;
10
16
  private urlCacheFile;
17
+ private embeddingCacheFile;
18
+ private incrementalStateFile;
11
19
  constructor(config: DocFreshnessConfig);
20
+ private validateCacheDir;
12
21
  private ensureCacheDir;
22
+ private validateCacheFile;
23
+ private readCacheFile;
24
+ private writeCacheFile;
25
+ private statCacheFile;
13
26
  /**
14
27
  * Save the code-to-doc graph
15
28
  */
@@ -31,6 +44,11 @@ export declare class CacheManager {
31
44
  * Load URL validation cache
32
45
  */
33
46
  loadUrlCache(): Promise<Record<string, UrlCacheEntry>>;
47
+ readEmbeddingCache(): Promise<string | null>;
48
+ writeEmbeddingCache(content: string): Promise<void>;
49
+ clearEmbeddingCache(): Promise<void>;
50
+ readIncrementalState(): Promise<string | null>;
51
+ writeIncrementalState(content: string): Promise<void>;
34
52
  /**
35
53
  * Clear all caches
36
54
  */
@@ -4,44 +4,130 @@ import crypto from 'crypto';
4
4
  import { CodeDocGraph } from '../graph/codeDocGraph.js';
5
5
  import { isWithinRoot, resolveProjectRoot } from '../utils/pathSecurity.js';
6
6
  /**
7
- * Manages caching of graph and URL validation results
7
+ * Resolves result-cache policy and manages persisted cache data
8
8
  */
9
9
  export class CacheManager {
10
10
  config;
11
- cacheDir;
11
+ rootDir;
12
+ rawDir;
13
+ policy;
12
14
  cacheFile;
13
15
  urlCacheFile;
16
+ embeddingCacheFile;
17
+ incrementalStateFile;
14
18
  constructor(config) {
15
19
  this.config = config;
16
- const rawDir = config.cache?.dir || config.graph?.cacheDir || '.doc-freshness-cache';
17
- const rootDir = resolveProjectRoot(config.rootDir);
18
- // Path traversal protection: resolve and verify cache dir stays within project root
19
- const resolved = path.resolve(rootDir, rawDir);
20
- if (!isWithinRoot(resolved, rootDir)) {
21
- throw new Error(`Cache directory "${rawDir}" resolves outside project root`);
20
+ this.rawDir = config.cache?.dir || config.graph?.cacheDir || '.doc-freshness-cache';
21
+ this.rootDir = resolveProjectRoot(config.rootDir);
22
+ const resolved = path.resolve(this.rootDir, this.rawDir);
23
+ this.policy = Object.freeze({ enabled: config.cache?.enabled !== false, dir: resolved });
24
+ this.cacheFile = path.join(this.policy.dir, 'graph-cache.json');
25
+ this.urlCacheFile = path.join(this.policy.dir, 'url-cache.json');
26
+ this.embeddingCacheFile = path.join(this.policy.dir, 'embedding-cache.json');
27
+ this.incrementalStateFile = path.join(this.policy.dir, 'file-hashes.json');
28
+ if (this.policy.enabled) {
29
+ this.validateCacheDir();
30
+ }
31
+ }
32
+ validateCacheDir() {
33
+ if (this.policy.dir === this.rootDir || !isWithinRoot(this.policy.dir, this.rootDir)) {
34
+ throw new Error(`Cache directory "${this.rawDir}" must resolve to a strict descendant of project root`);
35
+ }
36
+ const realRoot = fs.realpathSync(this.rootDir);
37
+ let ancestor = this.policy.dir;
38
+ while (!fs.existsSync(ancestor)) {
39
+ const parent = path.dirname(ancestor);
40
+ if (parent === ancestor) {
41
+ throw new Error(`Cache directory "${this.rawDir}" has no existing ancestor`);
42
+ }
43
+ ancestor = parent;
44
+ }
45
+ const realAncestor = fs.realpathSync(ancestor);
46
+ const realCacheDir = path.resolve(realAncestor, path.relative(ancestor, this.policy.dir));
47
+ if (realCacheDir === realRoot || !isWithinRoot(realCacheDir, realRoot)) {
48
+ throw new Error(`Cache directory "${this.rawDir}" must resolve to a strict descendant of project root`);
22
49
  }
23
- this.cacheDir = resolved;
24
- this.cacheFile = path.join(this.cacheDir, 'graph-cache.json');
25
- this.urlCacheFile = path.join(this.cacheDir, 'url-cache.json');
26
50
  }
27
51
  async ensureCacheDir() {
28
- await fs.promises.mkdir(this.cacheDir, { recursive: true });
52
+ this.validateCacheDir();
53
+ await fs.promises.mkdir(this.policy.dir, { recursive: true });
54
+ }
55
+ validateCacheFile(filePath) {
56
+ this.validateCacheDir();
57
+ let fileStats;
58
+ try {
59
+ fileStats = fs.lstatSync(filePath);
60
+ }
61
+ catch (error) {
62
+ if (error.code === 'ENOENT') {
63
+ return;
64
+ }
65
+ throw error;
66
+ }
67
+ if (fileStats.isSymbolicLink()) {
68
+ throw new Error(`Cache file "${path.basename(filePath)}" must not be a symbolic link`);
69
+ }
70
+ }
71
+ async readCacheFile(filePath) {
72
+ if (!this.policy.enabled) {
73
+ return null;
74
+ }
75
+ this.validateCacheFile(filePath);
76
+ try {
77
+ return await fs.promises.readFile(filePath, 'utf-8');
78
+ }
79
+ catch {
80
+ return null;
81
+ }
82
+ }
83
+ async writeCacheFile(filePath, content) {
84
+ if (!this.policy.enabled) {
85
+ return;
86
+ }
87
+ await this.ensureCacheDir();
88
+ this.validateCacheFile(filePath);
89
+ const tempFile = path.join(this.policy.dir, `.${path.basename(filePath)}.${crypto.randomUUID()}.tmp`);
90
+ try {
91
+ await fs.promises.writeFile(tempFile, content, { encoding: 'utf-8', flag: 'wx' });
92
+ this.validateCacheFile(filePath);
93
+ await fs.promises.rename(tempFile, filePath);
94
+ }
95
+ finally {
96
+ await fs.promises.rm(tempFile, { force: true }).catch(() => { });
97
+ }
98
+ }
99
+ async statCacheFile(filePath) {
100
+ if (!this.policy.enabled) {
101
+ return null;
102
+ }
103
+ this.validateCacheFile(filePath);
104
+ try {
105
+ return await fs.promises.stat(filePath);
106
+ }
107
+ catch {
108
+ return null;
109
+ }
29
110
  }
30
111
  /**
31
112
  * Save the code-to-doc graph
32
113
  */
33
114
  async saveGraph(graph) {
34
- await this.ensureCacheDir();
115
+ if (!this.policy.enabled) {
116
+ return;
117
+ }
35
118
  const data = graph.serialize();
36
119
  data.configHash = this.getConfigHash();
37
- await fs.promises.writeFile(this.cacheFile, JSON.stringify(data, null, 2));
120
+ await this.writeCacheFile(this.cacheFile, JSON.stringify(data, null, 2));
38
121
  }
39
122
  /**
40
123
  * Load the cached graph
41
124
  */
42
125
  async loadGraph() {
126
+ const content = await this.readCacheFile(this.cacheFile);
127
+ if (content === null) {
128
+ return null;
129
+ }
43
130
  try {
44
- const content = await fs.promises.readFile(this.cacheFile, 'utf-8');
45
131
  const data = JSON.parse(content);
46
132
  return CodeDocGraph.deserialize(data);
47
133
  }
@@ -53,7 +139,7 @@ export class CacheManager {
53
139
  * Check if cache is valid based on config hash and git state
54
140
  */
55
141
  isCacheValid(graph, currentCommit) {
56
- if (!graph) {
142
+ if (!this.policy.enabled || !graph) {
57
143
  return false;
58
144
  }
59
145
  if (!graph.buildTimestamp) {
@@ -82,31 +168,48 @@ export class CacheManager {
82
168
  * Save URL validation cache
83
169
  */
84
170
  async saveUrlCache(urlResults) {
85
- await this.ensureCacheDir();
86
- await fs.promises.writeFile(this.urlCacheFile, JSON.stringify(urlResults, null, 2));
171
+ await this.writeCacheFile(this.urlCacheFile, JSON.stringify(urlResults, null, 2));
87
172
  }
88
173
  /**
89
174
  * Load URL validation cache
90
175
  */
91
176
  async loadUrlCache() {
177
+ const content = await this.readCacheFile(this.urlCacheFile);
178
+ if (content === null) {
179
+ return {};
180
+ }
92
181
  try {
93
- const content = await fs.promises.readFile(this.urlCacheFile, 'utf-8');
94
182
  return JSON.parse(content);
95
183
  }
96
184
  catch {
97
185
  return {};
98
186
  }
99
187
  }
188
+ async readEmbeddingCache() {
189
+ return this.readCacheFile(this.embeddingCacheFile);
190
+ }
191
+ async writeEmbeddingCache(content) {
192
+ await this.writeCacheFile(this.embeddingCacheFile, content);
193
+ }
194
+ async clearEmbeddingCache() {
195
+ if (!this.policy.enabled) {
196
+ return;
197
+ }
198
+ this.validateCacheFile(this.embeddingCacheFile);
199
+ await fs.promises.rm(this.embeddingCacheFile, { force: true });
200
+ }
201
+ async readIncrementalState() {
202
+ return this.readCacheFile(this.incrementalStateFile);
203
+ }
204
+ async writeIncrementalState(content) {
205
+ await this.writeCacheFile(this.incrementalStateFile, content);
206
+ }
100
207
  /**
101
208
  * Clear all caches
102
209
  */
103
210
  async clearCache() {
104
- try {
105
- await fs.promises.rm(this.cacheDir, { recursive: true });
106
- }
107
- catch {
108
- // Directory doesn't exist
109
- }
211
+ this.validateCacheDir();
212
+ await fs.promises.rm(this.policy.dir, { recursive: true, force: true });
110
213
  }
111
214
  /**
112
215
  * Get cache statistics
@@ -118,21 +221,16 @@ export class CacheManager {
118
221
  urlCacheSize: 0,
119
222
  lastUpdated: null,
120
223
  };
121
- try {
122
- const graphStat = await fs.promises.stat(this.cacheFile);
123
- stats.exists = true;
124
- stats.graphSize = graphStat.size;
125
- stats.lastUpdated = graphStat.mtime;
126
- }
127
- catch {
128
- // File doesn't exist
224
+ if (!this.policy.enabled) {
225
+ return stats;
129
226
  }
130
- try {
131
- const urlStat = await fs.promises.stat(this.urlCacheFile);
132
- stats.urlCacheSize = urlStat.size;
133
- }
134
- catch {
135
- // File doesn't exist
227
+ const [graphStat, urlStat, embeddingStat, incrementalStat] = await Promise.all([this.cacheFile, this.urlCacheFile, this.embeddingCacheFile, this.incrementalStateFile].map((file) => this.statCacheFile(file)));
228
+ const existingStats = [graphStat, urlStat, embeddingStat, incrementalStat].filter((stat) => stat !== null);
229
+ if (existingStats.length > 0) {
230
+ stats.exists = true;
231
+ stats.graphSize = graphStat?.size ?? 0;
232
+ stats.urlCacheSize = urlStat?.size ?? 0;
233
+ stats.lastUpdated = new Date(Math.max(...existingStats.map((stat) => stat.mtimeMs)));
136
234
  }
137
235
  return stats;
138
236
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cacheManager.js","sourceRoot":"","sources":["../../src/cache/cacheManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cacheManager.js","sourceRoot":"","sources":["../../src/cache/cacheManager.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import fs from 'fs';
2
+ import os from 'os';
2
3
  import path from 'path';
3
4
  import { CacheManager } from './cacheManager.js';
4
5
  import { CodeDocGraph } from '../graph/codeDocGraph.js';
@@ -11,12 +12,90 @@ describe('CacheManager', () => {
11
12
  afterAll(async () => {
12
13
  await fs.promises.rm(cacheDir, { recursive: true, force: true }).catch(() => { });
13
14
  });
14
- it('throws if cache dir resolves outside project root', () => {
15
+ it('rejects cache directories outside the project root', async () => {
15
16
  const badConfig = {
16
17
  rootDir: '/project',
17
18
  cache: { dir: '../../etc/evil' },
18
19
  };
19
- expect(() => new CacheManager(badConfig)).toThrow('outside project root');
20
+ expect(() => new CacheManager(badConfig)).toThrow('strict descendant of project root');
21
+ const disabledManager = new CacheManager({ ...badConfig, cache: { ...badConfig.cache, enabled: false } });
22
+ await expect(disabledManager.clearCache()).rejects.toThrow('strict descendant of project root');
23
+ });
24
+ it('rejects the project root itself without deleting it', async () => {
25
+ const rootDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doc-freshness-cache-root-'));
26
+ const sentinel = path.join(rootDir, 'sentinel');
27
+ await fs.promises.writeFile(sentinel, 'keep');
28
+ expect(() => new CacheManager({ rootDir, cache: { enabled: true, dir: '.' } })).toThrow('strict descendant of project root');
29
+ expect(() => new CacheManager({ rootDir, cache: { enabled: true, dir: rootDir } })).toThrow('strict descendant of project root');
30
+ const disabledManager = new CacheManager({ rootDir, cache: { enabled: false, dir: rootDir } });
31
+ await expect(disabledManager.clearCache()).rejects.toThrow('strict descendant of project root');
32
+ expect(await fs.promises.readFile(sentinel, 'utf-8')).toBe('keep');
33
+ await fs.promises.rm(rootDir, { recursive: true, force: true });
34
+ });
35
+ it('rejects cache symlinks that escape the project root', async () => {
36
+ const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doc-freshness-cache-link-'));
37
+ const rootDir = path.join(tempDir, 'root');
38
+ const outsideDir = path.join(tempDir, 'outside');
39
+ const cacheLink = path.join(rootDir, 'cache');
40
+ const sentinel = path.join(outsideDir, 'sentinel');
41
+ await fs.promises.mkdir(rootDir);
42
+ await fs.promises.mkdir(outsideDir);
43
+ await fs.promises.writeFile(sentinel, 'keep');
44
+ await fs.promises.symlink(outsideDir, cacheLink);
45
+ expect(() => new CacheManager({ rootDir, cache: { enabled: true, dir: 'cache/nested' } })).toThrow('strict descendant of project root');
46
+ const disabledManager = new CacheManager({ rootDir, cache: { enabled: false, dir: 'cache/nested' } });
47
+ await disabledManager.saveUrlCache({ test: { result: { valid: true }, timestamp: Date.now() } });
48
+ await expect(disabledManager.clearCache()).rejects.toThrow('strict descendant of project root');
49
+ expect(await fs.promises.readdir(outsideDir)).toEqual(['sentinel']);
50
+ expect(await fs.promises.readFile(sentinel, 'utf-8')).toBe('keep');
51
+ await fs.promises.rm(tempDir, { recursive: true, force: true });
52
+ });
53
+ it('revalidates containment after a safe cache ancestor is replaced by a symlink', async () => {
54
+ const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doc-freshness-cache-swap-'));
55
+ const rootDir = path.join(tempDir, 'root');
56
+ const outsideDir = path.join(tempDir, 'outside');
57
+ const cacheAncestor = path.join(rootDir, 'results');
58
+ await fs.promises.mkdir(path.join(cacheAncestor, 'cache'), { recursive: true });
59
+ await fs.promises.mkdir(outsideDir);
60
+ await fs.promises.writeFile(path.join(outsideDir, 'sentinel'), 'keep');
61
+ const manager = new CacheManager({ rootDir, cache: { enabled: true, dir: 'results/cache' } });
62
+ await fs.promises.rm(cacheAncestor, { recursive: true, force: true });
63
+ await fs.promises.symlink(outsideDir, cacheAncestor);
64
+ await expect(manager.saveUrlCache({ test: { result: { valid: true }, timestamp: Date.now() } })).rejects.toThrow('strict descendant of project root');
65
+ await expect(manager.writeEmbeddingCache('{}')).rejects.toThrow('strict descendant of project root');
66
+ expect(await fs.promises.readdir(outsideDir)).toEqual(['sentinel']);
67
+ await fs.promises.rm(tempDir, { recursive: true, force: true });
68
+ });
69
+ it('rejects symbolic links at final cache file paths', async () => {
70
+ const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doc-freshness-cache-file-link-'));
71
+ const rootDir = path.join(tempDir, 'root');
72
+ const cachePath = path.join(rootDir, 'cache');
73
+ const sentinel = path.join(tempDir, 'sentinel');
74
+ await fs.promises.mkdir(cachePath, { recursive: true });
75
+ await fs.promises.writeFile(sentinel, 'keep');
76
+ await fs.promises.symlink(sentinel, path.join(cachePath, 'url-cache.json'));
77
+ const manager = new CacheManager({ rootDir, cache: { enabled: true, dir: 'cache' } });
78
+ await expect(manager.loadUrlCache()).rejects.toThrow('must not be a symbolic link');
79
+ await expect(manager.saveUrlCache({ test: { result: { valid: true }, timestamp: Date.now() } })).rejects.toThrow('must not be a symbolic link');
80
+ expect(await fs.promises.readFile(sentinel, 'utf-8')).toBe('keep');
81
+ await fs.promises.rm(tempDir, { recursive: true, force: true });
82
+ });
83
+ it('atomically replaces a hard-linked cache file without changing its other link', async () => {
84
+ const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doc-freshness-cache-hard-link-'));
85
+ const rootDir = path.join(tempDir, 'root');
86
+ const cachePath = path.join(rootDir, 'cache');
87
+ const cacheFile = path.join(cachePath, 'url-cache.json');
88
+ const sentinel = path.join(tempDir, 'sentinel');
89
+ const urlData = { 'https://example.com': { result: { valid: true }, timestamp: Date.now() } };
90
+ await fs.promises.mkdir(cachePath, { recursive: true });
91
+ await fs.promises.writeFile(sentinel, 'keep');
92
+ await fs.promises.link(sentinel, cacheFile);
93
+ const manager = new CacheManager({ rootDir, cache: { enabled: true, dir: 'cache' } });
94
+ await manager.saveUrlCache(urlData);
95
+ expect(await fs.promises.readFile(sentinel, 'utf-8')).toBe('keep');
96
+ expect(await manager.loadUrlCache()).toEqual(urlData);
97
+ expect(await fs.promises.readdir(cachePath)).toEqual(['url-cache.json']);
98
+ await fs.promises.rm(tempDir, { recursive: true, force: true });
20
99
  });
21
100
  describe('graph operations', () => {
22
101
  it('saves and loads a graph', async () => {
@@ -51,6 +130,36 @@ describe('CacheManager', () => {
51
130
  const manager = new CacheManager(freshConfig);
52
131
  expect(await manager.loadUrlCache()).toEqual({});
53
132
  });
133
+ it('does not load or save URL results when caching is disabled', async () => {
134
+ const disabledDir = path.join(cacheDir, 'disabled');
135
+ const cacheFile = path.join(disabledDir, 'url-cache.json');
136
+ await fs.promises.mkdir(disabledDir, { recursive: true });
137
+ await fs.promises.writeFile(cacheFile, '{"sentinel":true}');
138
+ const manager = new CacheManager({
139
+ rootDir: process.cwd(),
140
+ cache: { enabled: false, dir: path.relative(process.cwd(), disabledDir) },
141
+ });
142
+ expect(await manager.loadUrlCache()).toEqual({});
143
+ await manager.saveUrlCache({ test: { result: { valid: true }, timestamp: Date.now() } });
144
+ expect(await fs.promises.readFile(cacheFile, 'utf-8')).toBe('{"sentinel":true}');
145
+ });
146
+ it('treats ordinary read failures as cache misses', async () => {
147
+ const manager = new CacheManager(config);
148
+ const readSpy = vi.spyOn(fs.promises, 'readFile').mockRejectedValue(Object.assign(new Error('denied'), { code: 'EACCES' }));
149
+ expect(await manager.loadUrlCache()).toEqual({});
150
+ expect(await manager.loadGraph()).toBeNull();
151
+ expect(await manager.readEmbeddingCache()).toBeNull();
152
+ readSpy.mockRestore();
153
+ });
154
+ it('propagates final-file safety check failures other than absence', async () => {
155
+ const manager = new CacheManager(config);
156
+ const error = Object.assign(new Error('denied'), { code: 'EACCES' });
157
+ const lstatSpy = vi.spyOn(fs, 'lstatSync').mockImplementationOnce(() => {
158
+ throw error;
159
+ });
160
+ await expect(manager.loadUrlCache()).rejects.toBe(error);
161
+ lstatSpy.mockRestore();
162
+ });
54
163
  });
55
164
  describe('isCacheValid', () => {
56
165
  it('returns false for null graph', () => {
@@ -97,6 +206,14 @@ describe('CacheManager', () => {
97
206
  const manager = new CacheManager(freshConfig);
98
207
  await expect(manager.clearCache()).resolves.not.toThrow();
99
208
  });
209
+ it('propagates removal failures', async () => {
210
+ const manager = new CacheManager(config);
211
+ const error = Object.assign(new Error('permission denied'), { code: 'EACCES' });
212
+ const rmSpy = vi.spyOn(fs.promises, 'rm').mockRejectedValueOnce(error);
213
+ await expect(manager.clearCache()).rejects.toBe(error);
214
+ expect(rmSpy).toHaveBeenCalledWith(cacheDir, { recursive: true, force: true });
215
+ rmSpy.mockRestore();
216
+ });
100
217
  });
101
218
  describe('isCacheValid - configHash', () => {
102
219
  it('returns false when configHash differs', () => {
@@ -131,11 +248,22 @@ describe('CacheManager', () => {
131
248
  expect(stats.exists).toBe(false);
132
249
  expect(stats.lastUpdated).toBeNull();
133
250
  });
134
- it('returns URL cache size when URL cache exists', async () => {
135
- const manager = new CacheManager(config);
251
+ it('reports a populated result cache without a graph cache', async () => {
252
+ const manager = new CacheManager({
253
+ rootDir: process.cwd(),
254
+ cache: { dir: '.doc-freshness-cache/test-cache/url-only-stats' },
255
+ });
136
256
  await manager.saveUrlCache({ 'https://x.com': { result: { valid: true }, timestamp: Date.now() } });
137
257
  const stats = await manager.getCacheStats();
258
+ expect(stats.exists).toBe(true);
138
259
  expect(stats.urlCacheSize).toBeGreaterThan(0);
260
+ expect(stats.lastUpdated).toBeInstanceOf(Date);
261
+ });
262
+ it('treats ordinary stat failures as missing cache files', async () => {
263
+ const manager = new CacheManager(config);
264
+ const statSpy = vi.spyOn(fs.promises, 'stat').mockRejectedValue(Object.assign(new Error('denied'), { code: 'EACCES' }));
265
+ expect(await manager.getCacheStats()).toEqual({ exists: false, graphSize: 0, urlCacheSize: 0, lastUpdated: null });
266
+ statSpy.mockRestore();
139
267
  });
140
268
  });
141
269
  });
@@ -1 +1 @@
1
- {"version":3,"file":"cacheManager.test.js","sourceRoot":"","sources":["../../src/cache/cacheManager.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cacheManager.test.js","sourceRoot":"","sources":["../../src/cache/cacheManager.test.ts"],"names":[],"mappings":"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"}