Purpose
-------
FS-510 - incremental lint cache. Content-hash keyed so unchanged files
are not re-linted on subsequent runs.
Responsibilities
----------------
- Compute deterministic content hashes for source files.
- Compute the linter's own code identity, so an edit to a module that
decides a verdict invalidates every cached verdict (plan 265).
- Store and retrieve per-file lint results from a JSON cache file.
- Invalidate entries when file content, active rules, the OCT version or
the linter's own code change.
- Thread-safe read/write via ``threading.Lock``.
Diagnostics
-----------
Domain: OCT-LINTER
Levels:
L2 - (none) the cache save is reported at L3
L3 - cache hits/misses, the entry count at save, the header field
that caused a whole-store drop, and an unreadable linter package
L4 - cache I/O details, including the path loaded from
Contracts
---------
- Cache file lives at ``.option_c/cache/lint-cache.json``.
- Corrupt or missing cache file is silently replaced (no crash).
- Cache is never authoritative - a ``--no-cache`` flag bypasses reads.
- The linter identity is a STORE-level property, not a per-entry one: a
linter edit invalidates everything, so ``get``/``put`` keep their
signatures and the per-entry key is unchanged.
- An unreadable linter package yields the stable string ``"unavailable"``
rather than a guessed digest, so a frozen install still caches.
- Every user of the shared store (``oct lint`` and ``oct health``) builds
it with :func:`current_linter_identity`. Two users with different
identities discard each other's entries on every load.
Dependencies
------------
- oct.core.diagnostics (_dbg structured logger)
| str oct.linter.lint_cache.linter_identity_hash |
( |
Path | package_dir | ) |
|
Return a SHA-256 hex digest of the linter's own code (plan 265).
The digest covers every ``*.py`` directly under *package_dir* plus
the verdict-deciding files named in ``_EXTRA_IDENTITY_FILES``, sorted
by their path relative to *package_dir*'s parent. Each file's
contribution is prefixed by that relative path, so a rename moves the
digest even when no byte of any file changes.
Returns ``IDENTITY_UNAVAILABLE`` when the package cannot be read
(a frozen or zipped install), logging the reason once; a guessed
digest would be worse than a stable sentinel.
Definition at line 89 of file lint_cache.py.