Caching System
Understanding the PromptShield CacheManager.
To achieve split-second feedback on large monolithic repositories, @promptshield/workspace implements a zero-configuration persistent cache layer.
The cache engine is designed around three strict principles:
- Agility: Cache writes are "fire-and-forget". They must never block scanner throughput. Operations continue even if a cache write fails due to permissions.
- Base-lining: The cache stores the raw scan results computed at
minSeverity: "LOW"with inline directives enabled. Presentation filtering (e.g. CLI flags forminSeverity: "CRITICAL") is always calculated in-memory after cache retrieval. This ensures changing CLI flags does not require a cache rebuild. - Validation: An entry is considered valid immediately if its file modification time (
mtimeMs) and file size exactly match the cached metadata.
Cache Modes
The CacheManager supports multiple storage architectures to accommodate distinct repository sizes without requiring user intervention.
single
All cache entries are stored in a single cache.json file inside the .promptshield artifact directory.
- Pros: Compact, fewer filesystem allocations, easy to inspect.
- Cons: Requires advisory locking to prevent CLI/LSP race conditions. Write-heavy for massive repos.
- Best For: Small to medium repositories.
split
Each hashed file path receives its own tiny .json manifest globally housed in .promptshield/cache/.
- Pros: Perfectly lockless. Scales horizontally across parallel CI nodes or extreme repository thousands of files deep.
- Cons: Consumes more filesystem inodes.
- Best For: Large-scale monorepos (e.g., Next.js, VSCode).
auto (Default)
The engine counts your files on initialization.
- If size
> 1000files: Promotes tosplitmode. - If size
<= 1000files: Reverts tosinglemode.
The state is deterministically written to .promptshield/state.json.
Locking and TTL
When in single mode, PromptShield uses an advisory .lock file to prevent simultaneous cache corruption by concurrent CLI and LSP access.
If a process crashes while holding the lock, the underlying engine enforces a 10-minute TTL (Time To Live). If the lock age exceeds this threshold, it is considered stale, forcefully unlinked, and the newer process acquires ownership gracefully.
Schema Versioning
Caches inherently grow stale or break as detection rules evolve. The PromptShield engine natively tracks CACHE_SCHEMA_VERSION.
When the @promptshield/core engine is updated in a way that alters threat metadata, the schema version bumps. Missing or mismatched version manifests instantly invalidate either the entire single file or the specific split file, forcing a transparent re-scan.