From ec441095a68d26592fdf326c190e9451ae883f1c Mon Sep 17 00:00:00 2001 From: Rafael Richards Date: Sun, 10 May 2026 20:28:30 -0400 Subject: [PATCH] chore: docs/ prose-only gate + drop validate.py legacy fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two cleanups bundled: 1. make check-docs-prose — cross-repo guardrail enforcing that docs/ holds only human-readable prose (.md, .markdown, images, .gitkeep). Non-prose artifacts belong under dist/, examples/, templates/, or a top-level domain dir. Wired into CI alongside the existing manifest drift gate. Engine-free, fast, find-based. 2. validate.py _integrated_dir — drop the docs/integrated/ legacy fallback. The relocation back to top-level integrated/ (PR #6) is committed; the fallback's job was to support stale checkouts during the migration window, which is now closed. Three-line simplification — single canonical path. --- .github/workflows/ci.yml | 3 +++ Makefile | 20 +++++++++++++++++++- src/m_standard/tools/validate.py | 15 +++------------ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4208752..ac1fbb9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,3 +31,6 @@ jobs: - name: Manifest drift gate (Phase 0 / Track C) run: make check-manifest + + - name: docs/ prose-only gate + run: make check-docs-prose diff --git a/Makefile b/Makefile index 9a80308..d955dd3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: install hooks test test-lf watch lint format mypy cov check push pull \ sources sources-anno sources-ydb serve-anno extract reconcile validate all clean \ - integrated check-manifest + integrated check-manifest check-docs-prose PYTHON := .venv/bin/python PYTEST := .venv/bin/pytest @@ -117,3 +117,21 @@ integrated: # every `exposes.*` payload still exists on disk and (for .json) parses. check-manifest: integrated $(PYTHON) tools/check-repo-meta.py dist/repo.meta.json + +# Guardrail: docs/ holds only human-readable prose. Non-prose artifacts +# (generated data, JSON/TSV output, copy-paste examples, scaffolding +# templates) belong under dist/, examples/, templates/, or a top-level +# domain-specific directory — not docs/. +check-docs-prose: + @if [ ! -d docs ]; then echo "check-docs-prose: no docs/ directory ✓"; exit 0; fi; \ + violations=$$(find docs -type f \ + ! -name '*.md' ! -name '*.markdown' \ + ! -name '*.png' ! -name '*.jpg' ! -name '*.jpeg' \ + ! -name '*.gif' ! -name '*.svg' ! -name '*.webp' \ + ! -name '.gitkeep'); \ + if [ -n "$$violations" ]; then \ + echo "ERROR: non-prose files under docs/ — move to dist/, examples/, templates/, or a top-level domain dir:" >&2; \ + echo "$$violations" >&2; \ + exit 1; \ + fi; \ + echo "check-docs-prose: docs/ is prose-only ✓" diff --git a/src/m_standard/tools/validate.py b/src/m_standard/tools/validate.py index 4752428..a9d6f24 100644 --- a/src/m_standard/tools/validate.py +++ b/src/m_standard/tools/validate.py @@ -34,19 +34,10 @@ def _integrated_dir(project_root: Path) -> Path: """Resolve the integrated/ directory location. - The canonical layout has `integrated/` at the repo root, alongside - `per-source/`, `schemas/`, `sources/`, and `src/`. The repo briefly - held it at `docs/integrated/` (3bfb947 .. its reversion); the - fallback is kept for one release cycle so a stale checkout still - validates. + `integrated/` lives at the repo root, alongside `per-source/`, + `schemas/`, `sources/`, and `src/`. """ - canonical = project_root / "integrated" - if canonical.is_dir(): - return canonical - legacy = project_root / "docs" / "integrated" - if legacy.is_dir(): - return legacy - return canonical + return project_root / "integrated" # Names that are ALWAYS tracked under sources// regardless of