Files
serverAppConfigs/scripts/check-okf.py
T
Frankandomp 1ed7f0ddf2 docs(agents): compress Key Lessons to one law per bullet, correct the FA-quants law
Key Lessons Learned 483 -> 340 lines. Every law survives; only the essays
went. Port-before-cut census over the diff: 454 deleted lines, 0 orphaned
facts (every number still has a holder in the vault).

- Each lesson is now one bullet with the page that owns the detail.
- De-duplicated the page's own internal repeats: the layer-split law was
  told twice (PCIe and ROCm sections), the FA-quants law twice more.
- CORRECTION, verified on dankclaw 2026-10-19: `GGML_CUDA_FA_ALL_QUANTS` is
  deprecated upstream (master's ggml/cmake/common.cmake tells you to use
  GGML_CUDA_FA_QUANTS=all), the successor's default pair list
  `q4_0-q4_0;q8_0-q8_0;f16-f16;bf16-bf16` compiles the quantized-KV kernels
  with the old flag OFF (master build-cuda cache: FA_ALL_QUANTS=OFF), and
  neither llama tree references the old macro under ggml/src/ggml-cuda/.
  The "required or prefill collapses ~12x" law is obsolete; the new law is
  to read the CMakeCache pair list.
- frank-zealot: ported the three facts AGENTS.md alone carried, and verified
  them against the host first — the 2026-10-18 13:16 cutover boot really did
  load PTQ1_0 at `new slot, n_ctx = 133888` x3 (journal), the mmproj fit
  check really printed 873.10 MiB against a 21,439 MiB projection, and the
  warmup spread is 2.6 -> 1,258 t/s prefill.
- New tooling: scripts/check-okf.py (OKF v0.1 conformance linter) and
  scripts/gen-vault-index.py (root index regenerated from frontmatter).

Co-Authored-By: omp <omq@openclaw.sh>
2026-10-19 02:51:32 -07:00

176 lines
6.7 KiB
Python
Executable File

#!/usr/bin/env python3
"""OKF v0.1 conformance linter for the docs vault (serverAppConfigs-docs).
The vault is an Open Knowledge Format bundle (omp-docs/references/okf-spec.md)
plus the maintenance discipline in okf-maintenance.md, plus this repo's own
index law (AGENTS.md -> *Documentation Policy*): an index is a locator, one row,
one clause, no numbers. Enforced here so a violation cannot be merged:
FRONTMATTER every non-reserved page has a parseable frontmatter block with a
non-empty, non-generic `type` (the spec's only hard rule)
DESCRIPTION every concept has a description that is not the title, is not a
truncation artifact (ends in an ellipsis), carries no digits and
fits the one-clause budget (<= 120 chars)
TIMESTAMP every concept has an ISO `timestamp`
INDEX-FM an index.md carries no frontmatter (it is a listing, not a concept)
INDEX-COVER every index.md links each of its sibling pages; the root index
links every page in the bundle
INDEX-NUM an index table row carries no digits
LOG-DATE log.md date headings are `## YYYY-MM-DD`, newest first
LENGTH no page exceeds 500 lines (under-split); body under 15 lines is
flagged as an over-split stub
Exit status is 1 when anything fails, so it gates a test.
"""
import datetime
import pathlib
import re
import sys
RESERVED = {"index.md", "log.md"}
GENERIC_TYPES = {"file", "document", "page", "note"}
DESC_MAX = 120
BODY_MIN = 15
LINE_MAX = 500
def split_frontmatter(text):
"""Return (frontmatter_raw_or_None, body)."""
if not text.startswith("---"):
return None, text
end = text.find("\n---", 3)
if end == -1:
return None, text
return text[3:end].strip("\n"), text[end + 4:]
def field(raw, key):
if raw is None:
return None
m = re.search(rf"^{key}:\s*(.*)$", raw, re.M)
return m.group(1).strip() if m else None
def is_iso_date(value):
v = value.strip().strip("\"'").split("+")[0].split("T")[0]
try:
datetime.date.fromisoformat(v)
return True
except ValueError:
return False
def vault_pages(vault):
return [p for p in sorted(vault.rglob("*.md"))
if ".AGENTTRASH" not in str(p) and ".obsidian" not in str(p)]
def concept_pages(vault):
return [p for p in vault_pages(vault) if p.name not in RESERVED]
def check_concepts(vault, fail):
for page in concept_pages(vault):
rel = str(page.relative_to(vault))
raw, body = split_frontmatter(page.read_text(errors="replace"))
if raw is None:
fail("FRONTMATTER", rel, "no frontmatter block")
continue
ty = field(raw, "type")
if not ty:
fail("FRONTMATTER", rel, "missing type")
elif ty.lower() in GENERIC_TYPES:
fail("FRONTMATTER", rel, f"generic type {ty!r}")
desc = (field(raw, "description") or "").strip().strip("\"'")
title = (field(raw, "title") or "").strip().strip("\"'")
if not desc or desc in ("-", "—"):
fail("DESCRIPTION", rel, "missing description")
elif desc == title:
fail("DESCRIPTION", rel, "description copies the title")
elif desc.endswith("…"):
fail("DESCRIPTION", rel, "description is a truncation artifact")
elif len(desc) > DESC_MAX:
fail("DESCRIPTION", rel, f"description is {len(desc)} chars (budget {DESC_MAX})")
elif re.search(r"\d", desc):
fail("DESCRIPTION", rel, "description carries numbers (index rows must not)")
ts = field(raw, "timestamp")
if not ts:
fail("TIMESTAMP", rel, "missing timestamp")
elif not is_iso_date(ts):
fail("TIMESTAMP", rel, f"unparseable timestamp {ts!r}")
lines = page.read_text(errors="replace").splitlines()
if len(lines) > LINE_MAX:
fail("LENGTH", rel, f"{len(lines)} lines (max {LINE_MAX})")
elif len([l for l in body.splitlines() if l.strip()]) < BODY_MIN:
fail("LENGTH", rel, "stub: fewer than %d body lines" % BODY_MIN)
def check_indexes(vault, fail):
root_index = vault / "index.md"
all_stems = {p.stem for p in concept_pages(vault)}
for index in sorted(vault.rglob("index.md")):
if ".AGENTTRASH" in str(index):
continue
rel = str(index.relative_to(vault))
text = index.read_text(errors="replace")
if text.startswith("---"):
fail("INDEX-FM", rel, "index carries frontmatter")
siblings = {p.stem for p in index.parent.glob("*.md") if p.name not in RESERVED}
for stem in sorted(siblings):
if f"[[{stem}]]" not in text:
fail("INDEX-COVER", rel, f"does not link sibling {stem}")
if index == root_index:
for stem in sorted(all_stems - {p.stem for p in index.parent.glob("*.md")}):
if f"[[{stem}]]" not in text:
fail("INDEX-COVER", rel, f"does not link {stem}")
for line in text.splitlines():
if line.startswith("|") and not re.match(r"^\|[\s-|]+$", line) and "Page" not in line:
if re.search(r"\d", line):
fail("INDEX-NUM", rel, f"row carries numbers: {line[:70]}")
def check_log(vault, fail):
for log in sorted(vault.rglob("log.md")):
if ".AGENTTRASH" in str(log):
continue
rel = str(log.relative_to(vault))
dates = []
for line in log.read_text(errors="replace").splitlines():
m = re.match(r"^##\s+(.+)$", line)
if not m:
continue
head = m.group(1).strip()
dm = re.match(r"^(\d{4}-\d{2}-\d{2})$", head)
if not dm:
fail("LOG-DATE", rel, f"heading {head!r} is not a bare YYYY-MM-DD")
continue
if not is_iso_date(dm.group(1)):
fail("LOG-DATE", rel, f"heading {head!r} is not a real date")
dates.append(dm.group(1))
if dates != sorted(dates, reverse=True):
bad = next(i for i in range(1, len(dates)) if dates[i] > dates[i - 1])
fail("LOG-DATE", rel, f"{dates[bad]} after {dates[bad - 1]}: not newest first")
def main(argv):
vault = pathlib.Path(argv[1] if len(argv) > 1 else "serverAppConfigs-docs")
if not vault.is_dir():
print(f"not a directory: {vault}")
return 2
failures = []
def fail(rule, page, msg):
failures.append(f"{rule:12} {page}: {msg}")
check_concepts(vault, fail)
check_indexes(vault, fail)
check_log(vault, fail)
print(f"{len(concept_pages(vault))} concept pages, {len(failures)} OKF violations")
for line in failures:
print(" " + line)
return 1 if failures else 0
if __name__ == "__main__":
sys.exit(main(sys.argv))