check-stale

41 beliefs (38 IN, 3 OUT)

The check-stale topic covers the staleness detection subsystem of the TMS, which verifies whether beliefs remain consistent with their source material on disk. This is a critical integrity mechanism: beliefs in the network are grounded in specific source files (with line ranges), and when those files change or disappear, the corresponding beliefs may no longer be accurate. The system works by comparing stored SHA-256 hashes against current file contents, using full 64-character hex digests (hash-file-full-sha256) rather than the truncated 16-character prefixes that were used previously (hash-truncation-is-16-hex, now OUT as that behavior was fixed in PR #40). A key limitation is that this mechanism can only detect source staleness — cases where the file itself changed — and cannot detect world staleness, where a belief has become outdated even though its source file is unchanged (check-stale-detects-source-staleness-only). This asymmetry also extends to node types: premises have source-level grounding that makes them verifiable, while derived beliefs can only be structurally validated by checking that their antecedents exist and are IN (premise-derived-verifiability-asymmetry).

The check_stale function is deliberately read-only (check-stale-is-read-only), returning a list of structured result dicts without mutating the network. An earlier duplicate belief (check-stale-report-only, now OUT) restated this same property. This contrasts with hash_sources, which does mutate the network by writing directly to node.source_hash (hash-sources-mutates-network), though it is safe to call repeatedly because it skips nodes that already have hashes unless force=True is passed (hash-sources-idempotent-without-force, hash-sources-is-additive-by-default). Neither function persists changes — the caller must save (check-stale-and-hash-sources-mutate-in-place). The check_stale function only examines IN nodes (check-stale-skips-out-nodes), requires both source and source_hash fields to be non-empty (check-stale-requires-both-source-fields), and uses two reason codes: "content_changed" when a file's hash differs and "source_deleted" when the file is missing from disk (stale-result-reasons). An earlier belief that missing files were silently skipped (missing-source-file-is-silent) is now OUT, reflecting a fix (issue #25) that introduced explicit source_deleted reporting with None hashes (check-stale-source-deleted-returns-none-hashes). Source path resolution follows a precedence chain through db_dir, agent repo, and repo-key-split strategies (resolve-source-path-db-dir-precedence), falling back to ~/git/<repo>/<path> by convention (resolve-source-defaults-to-home-git), and returns None rather than raising on missing files (resolve-source-path-never-raises).

The output of check_stale is carefully designed for programmatic consumption and CI integration. All result dicts share a uniform 6-key schema — node_id, old_hash, new_hash, source, source_path, reason — regardless of whether the reason is content_changed or source_deleted (check-stale-result-schema-uniform, result-schema-uniformity). Results are sorted lexicographically by node_id for deterministic output (check-stale-results-sorted-by-node-id, results-sorted-by-node-id), and no exceptions are raised even for error conditions like missing files (check-stale-never-raises-on-missing-files, staleness-results-are-dicts-not-exceptions). The cmd_check_stale wrapper exits nonzero when stale nodes are found (check-stale-exits-nonzero), making it directly usable as a CI or pre-commit gate without wrapper scripts (staleness-output-is-ci-pipeline-ready, staleness-is-conservative-ci-gate). Several higher-level beliefs synthesize these properties: the staleness gate is claimed to catch all forms of source drift without false negatives (staleness-gate-catches-all-drift), and staleness information survives the binary IN/OUT truth model through metadata preservation during import and compact output (staleness-information-survives-binary-truth-model, staleness-is-surfaced-despite-binary-truth-model). The TMS maps STALE status in beliefs.md to OUT during import (stale-maps-to-out, stale-maps-to-out-on-import), since there is no distinct STALE truth value in the data model — but downstream consumers can still distinguish intentional retractions from staleness-driven ones via metadata.