de28272914
Ships DOCS.md and the /docs route — a plain-prose translation of SPEC.md for users, distinct from the binding spec. Originating need was the admin-vs-owner role distinction on /admin/users (§6.1); response is a single guide that covers the framework's user-facing surfaces end-to-end (roles, proposing, branches, PRs, graduation, notifications). Mirrors /philosophy: markdown file at repo root + sibling backend loader + MarkdownPreview render. No schema migration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
62 lines
1.9 KiB
Python
62 lines
1.9 KiB
Python
"""User-facing docs source.
|
|
|
|
Mirrors `philosophy.py` shape. Serves `DOCS.md` from the repo root —
|
|
the framework's plain-prose user guide to roles, contribution flow,
|
|
and notification surfaces, distinct from the binding `SPEC.md`. Read
|
|
from disk on first call and cached in-process; the periodic
|
|
reconciler can call `refresh()` to pick up out-of-band edits.
|
|
|
|
`DOCS_PATH` overrides the default location if a deployment hosts the
|
|
file elsewhere (a meta-repo working-tree clone, a sync target, etc.).
|
|
"""
|
|
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] / "DOCS.md"
|
|
|
|
_lock = threading.Lock()
|
|
_cache: dict | None = None
|
|
|
|
|
|
def _resolved_path() -> Path:
|
|
override = os.environ.get("DOCS_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`.
|
|
"""
|
|
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("DOCS.md not found at %s — serving placeholder", path)
|
|
text = (
|
|
"# DOCS.md not found\n\n"
|
|
"The deployment is missing its user guide. Set "
|
|
"DOCS_PATH or place DOCS.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)
|