feat: add open-knowledge-format skill

Google's Open Knowledge Format (OKF) v0.1 — an open, vendor-neutral
spec for representing knowledge as markdown files with YAML frontmatter,
designed for AI agent consumption.

- SKILL.md: core instructions, frontmatter spec, conformance criteria,
  cross-linking rules, relationship to other formats, quick start
- references/spec-summary.md: full OKF v0.1 specification reference
- references/bundle-architecture.md: directory structure and conventions
- references/use-cases.md: real-world adoption and patterns
- scripts/okf-bundle-validate.py: validate OKF bundle structure
- assets/concept-template.md: template for creating concept files
- assets/example-bundle/: minimal conformant OKF bundle
This commit is contained in:
Magnus Hedemark
2026-06-18 12:18:35 -04:00
parent a1458820d1
commit caa46d9c05
14 changed files with 996 additions and 0 deletions
@@ -0,0 +1,336 @@
#!/usr/bin/env python3
"""
okf-bundle-validate.py — Validate an OKF v0.1 knowledge bundle.
Checks:
1. Every non-reserved .md file has parseable YAML frontmatter
2. Every frontmatter block has a non-empty "type" field
3. Reserved filenames (index.md, log.md) follow their defined structure
4. Cross-links point to existing concept files (soft warning)
5. No filename collisions between concept IDs
Usage:
python3 okf-bundle-validate.py <bundle-directory>
python3 okf-bundle-validate.py <bundle-directory> --fix-missing-types
python3 okf-bundle-validate.py <bundle-directory> --json
"""
import os
import sys
import json
import re
import argparse
from pathlib import Path
RESERVED = {"index.md", "log.md"}
DATE_HEADING_RE = re.compile(r"^##\s+\d{4}-\d{2}-\d{2}")
LINK_RE = re.compile(r"\[([^\]]+)\]\(([^)]+)\)")
MD_LINK_RE = re.compile(r"\]\(((?:/|\./|\.\./)?[^)]+\.md)\)")
class ValidationResult:
def __init__(self):
self.errors = []
self.warnings = []
self.info = []
self.stats = {
"concept_files": 0,
"reserved_files": 0,
"cross_links": 0,
"broken_links": 0,
}
def error(self, path, msg):
self.errors.append({"path": str(path), "message": msg})
def warning(self, path, msg):
self.warnings.append({"path": str(path), "message": msg})
def add_info(self, msg):
self.info.append(msg)
@property
def passed(self):
return len(self.errors) == 0
def to_dict(self):
return {
"passed": self.passed,
"errors": self.errors,
"warnings": self.warnings,
"info": self.info,
"stats": self.stats,
}
def summary(self):
parts = []
if self.errors:
parts.append(f"FAILED: {len(self.errors)} error(s)")
else:
parts.append("PASSED")
parts.append(f"{self.stats['concept_files']} concepts")
parts.append(f"{self.stats['reserved_files']} reserved files")
parts.append(f"{self.stats['cross_links']} cross-links")
if self.stats["broken_links"]:
parts.append(f"{self.stats['broken_links']} broken link(s)")
return ", ".join(parts)
def parse_frontmatter(content):
"""Parse YAML frontmatter from markdown content. Returns (fields, body, error)."""
if not content.startswith("---"):
return None, content, "File does not start with frontmatter delimiter"
# Find closing ---
end_idx = content.find("\n---", 3)
if end_idx == -1:
return None, content, "Frontmatter not closed (missing closing ---)"
yaml_block = content[3:end_idx].strip()
body = content[end_idx + 4:].strip()
if not yaml_block:
return {}, body, None
# Simple YAML parser for the subset OKF uses
fields = {}
current_key = None
list_mode = False
for line in yaml_block.split("\n"):
# Skip blank lines and comments
stripped = line.strip()
if not stripped or stripped.startswith("#"):
continue
# Tag list continuation
if list_mode and stripped.startswith("- "):
if isinstance(fields.get(current_key), list):
fields[current_key].append(stripped[2:])
continue
else:
list_mode = False
# Key-value pair
if ":" in stripped and not stripped.startswith("- "):
colon_idx = stripped.index(":")
key = stripped[:colon_idx].strip()
value = stripped[colon_idx + 1:].strip()
current_key = key
if not value or value == "|" or value == ">":
fields[key] = ""
elif value.startswith("[") and value.endswith("]"):
# Inline list
inner = value[1:-1]
items = [item.strip().strip("'\"") for item in inner.split(",") if item.strip()]
fields[key] = items
elif value.startswith("- "):
list_mode = True
fields[key] = [value[2:]]
elif value.lower() == "true":
fields[key] = True
elif value.lower() == "false":
fields[key] = False
else:
# Remove surrounding quotes
if (value.startswith("'") and value.endswith("'")) or \
(value.startswith('"') and value.endswith('"')):
value = value[1:-1]
fields[key] = value
return fields, body, None
def collect_md_files(bundle_path):
"""Collect all .md files in the bundle directory."""
md_files = []
for root, dirs, files in os.walk(bundle_path):
# Skip hidden dirs
dirs[:] = [d for d in dirs if not d.startswith(".")]
for f in files:
if f.endswith(".md"):
abs_path = Path(root) / f
rel_path = abs_path.relative_to(bundle_path)
md_files.append(rel_path)
return sorted(md_files)
def check_index_file(path, content, result):
"""Check an index.md file follows OKF conventions."""
lines = content.strip().split("\n")
# Check for frontmatter (should NOT have it, except at bundle root)
if content.startswith("---"):
# Only allowed at bundle root for okf_version
if str(path) != "index.md":
result.warning(path, "index.md in subdirectory contains frontmatter (should be frontmatter-free)")
else:
# Has frontmatter - check it only contains okf_version
end_idx = content.find("\n---", 3)
if end_idx != -1:
yaml_block = content[3:end_idx].strip()
if yaml_block and "okf_version" not in yaml_block:
result.warning(path, "Root index.md frontmatter should only contain okf_version")
def check_log_file(path, content, result):
"""Check a log.md file follows OKF conventions."""
lines = content.strip().split("\n")
date_headings = 0
for line in lines:
if DATE_HEADING_RE.match(line.strip()):
date_headings += 1
if date_headings == 0:
result.warning(path, "log.md has no ISO 8601 date headings (## YYYY-MM-DD)")
def validate_bundle(bundle_path, fix_missing_types=False):
"""Validate an OKF v0.1 bundle directory."""
result = ValidationResult()
bundle_path = Path(bundle_path).resolve()
if not bundle_path.is_dir():
result.error(bundle_path, "Not a directory")
return result
result.add_info(f"Bundle path: {bundle_path}")
md_files = collect_md_files(bundle_path)
if not md_files:
result.error(bundle_path, "No markdown files found in bundle")
return result
# Build concept ID map
concept_ids = {}
for rel_path in md_files:
stem = str(rel_path.with_suffix(""))
concept_ids[stem] = rel_path
# Validate each file
for rel_path in md_files:
abs_path = bundle_path / rel_path
filename = rel_path.name
try:
content = abs_path.read_text(encoding="utf-8")
except Exception as e:
result.error(rel_path, f"Cannot read file: {e}")
continue
is_reserved = filename in RESERVED
if is_reserved:
result.stats["reserved_files"] += 1
else:
result.stats["concept_files"] += 1
# Check frontmatter
fields, body, parse_err = parse_frontmatter(content)
if parse_err:
if is_reserved:
result.add_info(f"Reserved file {rel_path} has no frontmatter (expected for {filename})")
else:
result.error(rel_path, parse_err)
continue
# Check reserved file structure
if filename == "index.md" and is_reserved:
check_index_file(rel_path, content, result)
elif filename == "log.md" and is_reserved:
check_log_file(rel_path, content, result)
if is_reserved:
continue
# Check required 'type' field
if not fields or "type" not in fields or not fields.get("type"):
if fix_missing_types:
# We don't actually fix here — this is informational
result.error(rel_path, "Missing required 'type' field in frontmatter")
else:
result.error(rel_path, "Missing required 'type' field in frontmatter")
continue
# Check cross-links
md_links = MD_LINK_RE.findall(body) if body else []
for link in md_links:
result.stats["cross_links"] += 1
# Resolve relative links
if link.startswith("/"):
# Bundle-relative
target = link[1:].replace(".md", "")
elif link.startswith("./") or link.startswith("../"):
# Relative — resolve from file's directory
file_dir = str(rel_path.parent) if str(rel_path.parent) != "." else ""
target = os.path.normpath(os.path.join(file_dir, link)).replace(".md", "")
else:
# External URL or same-file anchor — skip
continue
# Remove anchors
target = target.split("#")[0]
if target and target not in concept_ids:
result.stats["broken_links"] += 1
result.warning(rel_path, f"Broken link to '{target}.md' (concept ID: {target})")
return result
def main():
parser = argparse.ArgumentParser(
description="Validate an OKF v0.1 knowledge bundle"
)
parser.add_argument(
"bundle",
help="Path to the OKF bundle directory"
)
parser.add_argument(
"--fix-missing-types",
action="store_true",
help="Flag missing type fields as errors (default: errors)"
)
parser.add_argument(
"--json",
action="store_true",
help="Output results as JSON"
)
args = parser.parse_args()
result = validate_bundle(args.bundle, fix_missing_types=args.fix_missing_types)
if args.json:
print(json.dumps(result.to_dict(), indent=2))
else:
print("\n" + "=" * 60)
print(f" OKF Bundle Validation: {result.summary()}")
print("=" * 60)
if result.errors:
print(f"\n Errors ({len(result.errors)}):")
for err in result.errors:
print(f"{err['path']}: {err['message']}")
if result.warnings:
print(f"\n Warnings ({len(result.warnings)}):")
for warn in result.warnings:
print(f"{warn['path']}: {warn['message']}")
if result.info:
print(f"\n Info:")
for msg in result.info:
print(f" {msg}")
print()
return 0 if result.passed else 1
if __name__ == "__main__":
sys.exit(main())