ADR-002: Implement OKF v0.1 bundle format in v0.1.0
Status: Accepted
Date: 2026-07-04
Drivers: @anomalyco
Supersedes: ADR-001
Context
ADR-001 deferred the OKF v0.1 directory-bundle format to v0.2.0. Two factors motivate revisiting this decision:
-
Real-world demand: The Google Python Style Guide bundle at
examples/google-python-style-guide/demonstrated that OKF bundles are the primary output users want fromknowledge create. A flat KMD file is not suitable for documentation consumption. -
Section-aware extraction: Processing HTML sources by section headings produces higher-quality concepts than tag-stripped flat text. The bundle format naturally maps to this section-per-concept structure.
Since the internal KnowledgeGraph model is format-agnostic, adding bundle
support requires only a new serializer (not model changes). The section-aware
HTML reader is an orthogonal improvement to the source-reader layer.
Options Considered
Option A: Implement bundle + section-aware extraction now
- Pro: Satisfies real user workflow (
knowledge create <url> -o <dir>). - Pro: Bundle serializer reuses existing
Conceptmodel — no data loss. - Pro: Section-aware HTML reader is a new source reader (like
MarkdownSourceReader), not a pipeline rewrite. - Pro: The example bundle at
examples/validates the output format. - Con: Adds surface area before v0.1.0 release.
- Con:
OKFDocument.save()needs a second output path (directory vs file).
Option B: Keep deferring to v0.2.0
- Pro: No new code before release.
- Con:
knowledge create <url> -o <dir>still produces a flat KMD file instead of the documented example bundle. - Con: Users must use a separate (removed) scripts to generate bundles.
Option C: Only implement bundle serializer, skip section-aware extraction
- Pro: Less code.
- Con: Extracted concepts from HTML are still low-quality (entities like “NoneType”, “Pros”) because flat tag-stripping loses section structure.
Decision
Accept Option A. Implement both the OKF v0.1 bundle serializer and the section-aware HTML source reader in v0.1.0.
Implementation
Bundle serializer (knowledge/kmd/bundle.py)
BundleSerializer(graph, output_dir)writes eachConceptto a Markdown file with YAML frontmatter (id,title,type,tags,source).- Concepts are grouped into subdirectories by
tagsmatching known category prefixes (e.g.language→rules/language/). - Auto-generates
index.mdfor each directory. - Writes
type: conceptfor leaf entries,type: indexfor directory indexes,type: bundlefor the root index.
Section-aware source reader (knowledge/llm/extractor.py)
LLMExtractorsplits source text by top-level headings (HTML<h2>or markdown##) using regex, then sends each section to an LLM via litellm.- The LLM converts the raw section content (HTML or markdown) into clean
Markdown and returns a structured JSON concept object with
id,name,description,tags, andlevel. - Supports any litellm-compatible model (OpenAI, Anthropic, Ollama, vLLM, etc.).
- Falls back to treating the entire document as a single section when no heading structure is detected.
SDK integration (knowledge/sdk.py)
Knowledge.create(source): fetches or reads the source, delegates toLLMExtractor.extract(), and returns aKnowledgeGraph.Knowledge.create_bundle(source, output_dir): fetches/reads, extracts, and serializes viaBundleSerializer.Knowledge.update(source, bundle_dir): re-extracts from source and overwrites the existing bundle.Knowledge.remove(concept_ids, bundle_dir): reads the existing bundle, removes the specified concept IDs, and re-serializes.
CLI (knowledge/cli.py)
knowledge create <input> <output>extracts concepts and writes OKF bundle.knowledge update <input> <bundle_dir>re-extracts and overwrites an existing bundle.knowledge remove <concept_id>... <bundle_dir>removes specific concepts from a bundle by their IDs.- All commands accept
--modelto select the LLM (defaultgpt-4o).
Consequences
Positive
knowledge create <url> <dir>produces the documented bundle format.- LLM-based extraction produces high-quality concepts from HTML sources, converting HTML formatting to clean Markdown faithfully.
- The
KnowledgeGraphmodel is format-agnostic;BundleSerializeris a pure serialization layer.
Negative
- Bundle output requires filesystem directory I/O, which is more complex than flat file writes.
- LLM extraction requires API access (OpenAI, Anthropic, or local model via Ollama) and adds latency and per-request cost compared to rule-based parsing.