"""§14.2 philosophy source. The spec names PHILOSOPHY.md as the body the `/philosophy` route renders, "sourced from the meta repo's main branch, cached and refreshed on the same cadence as RFC bodies (§4)." Slice 7 picks the disk-first shape: the file is checked into the app repo alongside SPEC.md, since it is the framework's design document rather than an RFC entry, and reading it from disk at process start (with a periodic re-read for hot edits) puts the framework's mission in front of the reader without an extra Gitea round-trip on the first hit. If a downstream deployment hosts PHILOSOPHY.md in the meta repo instead, the `PHILOSOPHY_PATH` env var can point at a working-tree clone or a sync target; the loader does not care which. """ from __future__ import annotations import logging import os import threading from pathlib import Path log = logging.getLogger(__name__) _DEFAULT_PATH = Path(__file__).resolve().parents[2] / "PHILOSOPHY.md" _lock = threading.Lock() _cache: dict | None = None def _resolved_path() -> Path: override = os.environ.get("PHILOSOPHY_PATH", "").strip() if override: return Path(override).expanduser().resolve() return _DEFAULT_PATH def load(force: bool = False) -> dict: """Return the cached `{body, path, mtime}` payload, reading from disk on first call or when `force=True`. The reconciler's sweep can call this with `force=True` to pick up out-of-band edits. """ global _cache with _lock: if _cache is not None and not force: return _cache path = _resolved_path() try: text = path.read_text(encoding="utf-8") mtime = path.stat().st_mtime except FileNotFoundError: log.warning("PHILOSOPHY.md not found at %s — serving placeholder", path) text = ( "# PHILOSOPHY.md not found\n\n" "The deployment is missing its philosophy document. Set " "PHILOSOPHY_PATH or place PHILOSOPHY.md at the project root." ) mtime = 0.0 _cache = {"body": text, "path": str(path), "mtime": mtime} return _cache def refresh() -> dict: """Force-reread from disk. Returns the new payload.""" return load(force=True)