okf

package module
v0.1.0-beta.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 16 Imported by: 0

README

go-okf

Go Reference

A standalone Go implementation of the Open Knowledge Format (OKF).

OKF v0.2 models a knowledge bundle as a directory of markdown files with YAML frontmatter, where each file is one concept and reserved index.md / log.md files provide directory listings and change history. go-okf is a pure-Go, dependency-light library for working with these bundles: parse and round-trip single concepts, load a whole bundle over an io/fs.FS, extract and deduplicate links/citations/resources, synthesize index content, and check conformance. Typed concepts are layered on via an extensible registry (Register / As / Concept.Typed) rather than a closed interface hierarchy.

Install

go get github.com/paultyng/go-okf

Usage

Load a bundle from a directory and list its concepts:

package main

import (
	"fmt"
	"os"

	okf "github.com/paultyng/go-okf"
)

func main() {
	b, err := okf.Load(os.DirFS("./my-bundle"))
	if err != nil {
		panic(err)
	}

	for _, c := range b.Concepts() {
		fmt.Printf("%s: %s\n", c.Type, c.Title)
	}
}

Or parse a single concept and write it back:

c, err := okf.Parse(data)
if err != nil {
	panic(err)
}
fmt.Println(c.Title)

out := c.Bytes() // frontmatter + verbatim body, ready to persist

Status

v0.2, beta (v0.1.0-beta.2 tagged). MIT licensed.

Documentation

Overview

Package okf implements the Open Knowledge Format (OKF) v0.2: a directory of markdown files with YAML frontmatter representing a knowledge bundle. See the OKF spec for the format definition.

The package is pure OKF: it has zero dependencies on any specific consumer's domain types. Extensibility is provided via a type registry (Register, As, Concept.Typed) rather than a closed interface hierarchy; AttestedComputation is the one built-in typed concept.

Parse a single concept with Parse and write it back with Concept.Bytes; load a whole bundle from an io/fs.FS with Load. The reserved index.md and log.md files are handled by Index and Log. Bundle.ExternalLinks derives a bundle's outbound resources, and Bundle.Conformance checks OKF conformance.

Core has no concrete filesystem coupling beyond stdlib io/fs.FS for reads; writes are caller-owned (the Bytes methods on Concept, Index, and Log return bytes, callers persist them). Core never calls time.Now: dates are passed in by the caller for determinism.

Index

Examples

Constants

View Source
const (
	StatusDraft      = "draft"
	StatusStable     = "stable"
	StatusDeprecated = "deprecated"
)

Lifecycle status values (OKF v0.2 §5.4). Status is a free string on Concept — these constants name the spec's fixed vocabulary without restricting parsing to it (permissive parsing never rejects an unknown value).

View Source
const AttestedComputationType = "Attested Computation"

AttestedComputationType is the concept `type` value with normative semantics under OKF v0.2 §10: a sanctioned way to compute a value, so a consumer can confirm the value was produced by running it. go-okf self-registers this single type; every other type string is free-form.

Variables

View Source
var MaxParseBytes = 1 << 20

MaxParseBytes bounds how many bytes of a Concept.Body are handed to the markdown parser during extraction (Links, Citations, FootnoteSourceIDs, Bundle.ExternalLinks, and the Attested Computation `# Computation` fence). goldmark's parser can be superlinear on adversarially nested markdown (deeply nested lists, blockquotes, emphasis runs), and Body is untrusted producer input with no other size bound in this package.

The stored Concept.Body is never mutated or truncated by this cap — only the bytes fed to the parser are bounded. A body longer than MaxParseBytes still round-trips and marshals in full; only extraction sees a truncated view, and so may miss a link, citation, footnote, or fence that starts beyond the cutoff.

The default (1 MiB) is generous, sized to avoid truncating legitimate documents. Consumers that feed fully-untrusted, adversarial input to this package should lower MaxParseBytes considerably. Set to 0 to disable the cap entirely.

Functions

func As

func As[T any](c *Concept) (*T, error)

As decodes the concept's merged full frontmatter (core fields plus Extra — every key) into T via yaml struct tags, so a caller-known type sees both the OKF core fields (title, description, ...) and its own custom keys. This is the compile-time path: it needs no registry entry. For decoding that As can't express, supply a custom func to Register instead.

Example

ExampleAs decodes a concept's merged frontmatter (core fields plus custom keys) straight into a caller-defined struct via yaml tags — the compile-time path that needs no registry entry.

package main

import (
	"fmt"

	okf "github.com/paultyng/go-okf"
)

// Playbook is a small consumer-defined concept type, registered below to
// demonstrate go-okf's extensibility story: a custom `type` value decoded
// through the package-level registry rather than a closed interface.
type Playbook struct {
	Title string `yaml:"title"`
	Owner string `yaml:"owner"`
}

func main() {
	c, err := okf.Parse([]byte("---\ntype: Playbook\ntitle: Incident response\nowner: team:sre\n---\n\nbody\n"))
	if err != nil {
		panic(err)
	}

	pb, err := okf.As[Playbook](c)
	if err != nil {
		panic(err)
	}

	fmt.Println(pb.Title, pb.Owner)
}
Output:
Incident response team:sre

func CanonicalURL

func CanonicalURL(raw string) string

CanonicalURL normalizes raw for comparison/identity only — it is never persisted or displayed; stored and emitted URLs stay verbatim. The normalization is deliberately narrow: lowercase scheme and host, strip a default port (:80 for http, :443 for https), drop the fragment, keep the query string, and treat an empty path as "/". Unparsable input is returned unchanged.

Example

ExampleCanonicalURL normalizes a URL for comparison only: scheme and host are lowercased, the default port and fragment are dropped, and the query string is preserved.

package main

import (
	"fmt"

	okf "github.com/paultyng/go-okf"
)

func main() {
	fmt.Println(okf.CanonicalURL("HTTPS://Example.com:443/path/?b=2&a=1#frag"))
}
Output:
https://example.com/path/?b=2&a=1

func Register

func Register(kind string, decode func(*Concept) (any, error))

Register adds a decoder for a concept `type` string to the package-level registry, modifiable externally at init() (modeled on image.RegisterFormat / database/sql.Register / Kubernetes' Scheme). go-okf ships exactly one built-in registration ("Attested Computation"); every other type string is free-form and consumers register their own decoders with zero changes to this package.

Example

ExampleRegister registers a decoder for a custom concept type and dispatches to it via Concept.Typed.

package main

import (
	"fmt"

	okf "github.com/paultyng/go-okf"
)

// Playbook is a small consumer-defined concept type, registered below to
// demonstrate go-okf's extensibility story: a custom `type` value decoded
// through the package-level registry rather than a closed interface.
type Playbook struct {
	Title string `yaml:"title"`
	Owner string `yaml:"owner"`
}

func main() {
	okf.Register("Playbook", func(c *okf.Concept) (any, error) {
		return okf.As[Playbook](c)
	})

	c, err := okf.Parse([]byte("---\ntype: Playbook\ntitle: Incident response\nowner: team:sre\n---\n\nbody\n"))
	if err != nil {
		panic(err)
	}

	v, ok := c.Typed()
	if !ok {
		panic("expected Playbook to be registered")
	}

	pb := v.(*Playbook)
	fmt.Println(pb.Title, pb.Owner)
}
Output:
Incident response team:sre

Types

type Actor

type Actor struct {
	By string    `yaml:"by"`
	At time.Time `yaml:"at"`
}

Actor identifies who or what performed an action (OKF v0.2 §7): an agent as "<producer>/<version>", a person as "human:<id>", or an automated process as "process:<id>". At is a full ISO 8601 datetime, distinct from Date (a bare calendar date).

func (*Actor) UnmarshalYAML

func (a *Actor) UnmarshalYAML(node *yaml.Node) error

UnmarshalYAML implements yaml.Unmarshaler. `by` decodes strictly (a malformed `by` still errors, matching the default struct-decode behavior this replaces). `at` is tolerant, mirroring Date: a syntactically-valid document with an unparseable or wrong-kind `at` scalar must never fail Concept parsing (permissive parsing, OKF v0.2 §11) — a bad `at` is treated as absent (zero Actor.At) rather than an error.

type AttestedComputation

type AttestedComputation struct {
	Runtime     string      `yaml:"runtime"`
	Parameters  []Parameter `yaml:"parameters,omitempty"`
	Computation string      `yaml:"computation,omitempty"`
	Executor    Executor    `yaml:"executor,omitempty"`
	Attester    Attester    `yaml:"attester,omitempty"`
}

AttestedComputation is the typed view of a `type: Attested Computation` concept (OKF v0.2 §10). It is parse-only: go-okf never runs an executor or attester, only records the contract and the means to check it.

Computation holds the `computation:` frontmatter path when present; when that key is absent, it instead holds the literal contents of the body's `# Computation` fenced or indented code block (§10.3), so callers always find "the computation" in one field regardless of which form the producer used.

func (*AttestedComputation) Validate

func (ac *AttestedComputation) Validate() []Violation

Validate implements Validator. `runtime` is the only "REQUIRED for this type" clause in the OKF v0.2 spec (§10.2).

type Attester

type Attester struct {
	Resource string `yaml:"resource,omitempty"`
}

Attester names the deterministic (no-LLM) check that inspects a receipt and returns a verdict.

type Bundle

type Bundle struct {
	// contains filtered or unexported fields
}

Bundle is an in-memory OKF knowledge bundle: concepts keyed by concept ID, plus any reserved files (index.md, log.md) found at each directory level.

func FromConcepts

func FromConcepts(concepts map[string]*Concept) *Bundle

FromConcepts builds a Bundle directly from an in-memory concept map, keyed by concept id string, without any filesystem involved.

func Load

func Load(fsys fs.FS) (*Bundle, error)

Load reads a bundle from any fs.FS (os.DirFS, embed.FS, fstest.MapFS, ...). It is permissive per OKF v0.2 §11: a concept file with unparsable frontmatter is skipped rather than failing the whole load, unknown types are accepted, and broken links are never checked here (link resolution is a consumer/extraction concern, not a load-time one).

Example

ExampleLoad builds a Bundle from an in-memory filesystem and lists its concepts in concept-id order.

package main

import (
	"fmt"
	"testing/fstest"

	okf "github.com/paultyng/go-okf"
)

func main() {
	fsys := fstest.MapFS{
		"tables/customers.md": &fstest.MapFile{Data: []byte("---\ntype: BigQuery Table\ntitle: Customers\n---\n\nbody\n")},
		"tables/orders.md":    &fstest.MapFile{Data: []byte("---\ntype: BigQuery Table\ntitle: Orders\n---\n\nbody\n")},
	}

	b, err := okf.Load(fsys)
	if err != nil {
		panic(err)
	}

	for _, c := range b.Concepts() {
		fmt.Println(c.Title)
	}
}
Output:
Customers
Orders

func (*Bundle) Citations

func (b *Bundle) Citations() []Citation

Citations returns the legacy `# Citations` entries across every concept.

func (*Bundle) Concept

func (b *Bundle) Concept(id string) (*Concept, bool)

Concept looks up a concept by id.

func (*Bundle) Concepts

func (b *Bundle) Concepts() []*Concept

Concepts returns every concept in the bundle, ordered by concept id.

func (*Bundle) Conformance

func (b *Bundle) Conformance() []Violation

Conformance checks every concept in the bundle against OKF v0.2 §11: the base rule (every concept has a non-empty `type`) plus any rules contributed by a registered type's Validator implementation. An empty return slice means the bundle is conformant. Conformance is permissive per spec: unknown types, unknown keys, broken links, and missing optional fields are never violations.

Example

ExampleBundle_Conformance checks a bundle against OKF v0.2 §11: a concept missing its required `type` produces one violation.

package main

import (
	"fmt"
	"testing/fstest"

	okf "github.com/paultyng/go-okf"
)

func main() {
	fsys := fstest.MapFS{
		"tables/orders.md": &fstest.MapFile{Data: []byte("---\ntitle: Orders\n---\n\nbody\n")},
	}
	b, err := okf.Load(fsys)
	if err != nil {
		panic(err)
	}

	for _, v := range b.Conformance() {
		fmt.Println(v.ConceptID, v.Rule)
	}
}
Output:
tables/orders type-required
func (b *Bundle) ExternalLinks() []ExternalLink

ExternalLinks merges every external reference across the bundle — frontmatter `resource:`, `sources[].resource`, legacy body `# Citations`, and inline body links — into one deduplicated list keyed by CanonicalURL. Metadata precedence, richest wins: resource/sources > citation > inline link. Origins collect every discovery site.

func (*Bundle) Index

func (b *Bundle) Index(dir string) (*Index, bool)

Index returns the parsed index.md at the given bundle-relative directory ("" for the bundle root), if one was loaded.

func (b *Bundle) Links() []Link

Links returns every markdown link across every concept in the bundle.

func (*Bundle) Log

func (b *Bundle) Log(dir string) (*Log, bool)

Log returns the parsed log.md at the given bundle-relative directory ("" for the bundle root), if one was loaded.

func (*Bundle) RegenerateIndexes

func (b *Bundle) RegenerateIndexes(synth Synthesizer) map[string][]byte

RegenerateIndexes synthesizes index.md content for every bundle directory that contains at least one concept (directly or via a subdirectory), mirroring the reference implementation: entries grouped by `type` and sorted by title within a directory's own index; subdirectories are listed under a "Subdirectories" heading, reusing a lone child's own description or invoking synth for multiple children. Directories with no concepts anywhere beneath them are not indexed — this is a deliberate simplification of the reference's raw directory listing, which will also list a subdirectory containing no concepts at all (see NOTES-priorart.md / build report for detail).

Returns bundle-relative directory path ("" for the bundle root) to rendered index.md bytes; callers persist.

Example

ExampleBundle_RegenerateIndexes synthesizes an index.md for a bundle, grouping concepts by type and sorting entries by title. Passing a nil okf.Synthesizer is fine here: no subdirectory summaries are needed.

package main

import (
	"fmt"

	okf "github.com/paultyng/go-okf"
)

func main() {
	b := okf.FromConcepts(map[string]*okf.Concept{
		"orders":    {Type: "BigQuery Table", Title: "Orders"},
		"customers": {Type: "BigQuery Table", Title: "Customers"},
	})

	indexes := b.RegenerateIndexes(nil)
	fmt.Print(string(indexes[""]))
}
Output:
# BigQuery Table

* [Customers](customers.md)
* [Orders](orders.md)

func (*Bundle) Resources

func (b *Bundle) Resources() []string

Resources returns the frontmatter `resource:` values across every concept, in concept-id order, skipping concepts with no resource set.

func (*Bundle) Sources

func (b *Bundle) Sources() []Source

Sources returns the §5.1 provenance entries across every concept.

type Citation

type Citation struct {
	Index int
	Title string
	URL   string
}

Citation is a legacy v0.1 body `# Citations` list entry (superseded by `sources` frontmatter in v0.2 — see OKF v0.2 §13.1). Index is the 1-based position within the list.

type Concept

type Concept struct {
	// Core frontmatter (OKF v0.2 §4.1).
	Type        string // REQUIRED — the type discriminator.
	Title       string
	Description string
	Resource    string // singular canonical URI (concept identity).
	Tags        []string

	// Provenance, trust, and lifecycle families (OKF v0.2 §5). All optional.
	Sources     []Source
	UsageWindow *UsageWindow // §5.1 — shared window for Sources[].UsageCount; a [Source] may override it.
	Generated   *Actor       // §5.2 — last content change; supersedes v0.1 `timestamp`.
	Verified    []Actor
	Status      string
	StaleAfter  *Date

	// Extra holds every other frontmatter key, preserved verbatim so
	// round-tripping never silently drops producer-defined fields. Because
	// it is a plain map[string]any (not an order-preserving structure),
	// keys serialize sorted (yaml.v3's default map behavior); authored key
	// order is not preserved.
	Extra map[string]any

	// Body is the markdown body, verbatim and opaque to this package.
	Body string
}

Concept is the concrete carrier for a single OKF concept document: a markdown file with YAML frontmatter. It is a concrete struct rather than an interface, since a concept is data (frontmatter + verbatim body) and round-trip safety demands a concrete carrier. Extensible typing is layered on top via As / Register / Concept.Typed (see registry.go).

func Parse

func Parse(data []byte) (*Concept, error)

Parse parses a concept document's raw bytes into a Concept. It tolerates documents with no frontmatter (frontmatter left zero-valued, all content treated as body) but returns an error for an unterminated frontmatter block or frontmatter that isn't a YAML mapping.

Example

ExampleParse parses a concept bound to a resource (OKF v0.2 §4.3) and reads its core frontmatter fields.

package main

import (
	"fmt"

	okf "github.com/paultyng/go-okf"
)

func main() {
	doc := []byte(`---
type: BigQuery Table
title: Customer Orders
description: One row per completed customer order across all channels.
resource: https://console.cloud.google.com/bigquery?p=acme&d=sales&t=orders
tags: [sales, orders, revenue]
---

# Schema

One row per completed order.
`)

	c, err := okf.Parse(doc)
	if err != nil {
		panic(err)
	}

	fmt.Println(c.Type)
	fmt.Println(c.Title)
	fmt.Println(c.Resource)
	fmt.Println(c.Tags)
}
Output:
BigQuery Table
Customer Orders
https://console.cloud.google.com/bigquery?p=acme&d=sales&t=orders
[sales orders revenue]

func (*Concept) AsAttestedComputation

func (c *Concept) AsAttestedComputation() (*AttestedComputation, bool)

AsAttestedComputation decodes c as an Attested Computation, returning (nil, false) when c is not of that type.

Example

ExampleConcept_AsAttestedComputation decodes an Attested Computation concept (OKF v0.2 §10.2): a sanctioned, re-runnable way to produce a value, plus the executor and attester that check it.

package main

import (
	"fmt"

	okf "github.com/paultyng/go-okf"
)

func main() {
	c, err := okf.Parse([]byte(`---
type: Attested Computation
title: Revenue for fiscal year
runtime: bigquery
parameters:
  - { name: year, type: integer, required: true }
executor:
  resource: references/skills/run-on-bq.md
  receipt: [job_id, executed_sql, result]
attester:
  resource: references/attesters/revenue.py
---

# Computation

    SELECT SUM(amount) AS revenue
    FROM finance.recognized_revenue
    WHERE fiscal_year = @year
`))
	if err != nil {
		panic(err)
	}

	ac, ok := c.AsAttestedComputation()
	if !ok {
		panic("expected an Attested Computation")
	}

	fmt.Println(ac.Runtime)
	fmt.Println(ac.Parameters[0].Name, ac.Parameters[0].Required)
	fmt.Println(ac.Executor.Resource)
	fmt.Println(ac.Attester.Resource)
}
Output:
bigquery
year true
references/skills/run-on-bq.md
references/attesters/revenue.py

func (*Concept) Bytes

func (c *Concept) Bytes() []byte

Bytes serializes the Concept back into a full document: frontmatter delimited by `---` lines followed by the verbatim body. Bytes is pure (no I/O); callers persist the returned bytes (see the filesystem abstraction notes in the package doc). It mirrors Index.Bytes and Log.Bytes.

Example

ExampleConcept_Bytes round-trips a concept through Parse and Bytes, showing that an unrecognized frontmatter key (Extra) and the body survive intact.

package main

import (
	"fmt"

	okf "github.com/paultyng/go-okf"
)

func main() {
	doc := []byte(`---
type: Playbook
title: Incident response
owner: team:sre
---

# Steps

1. Check the dashboard.
`)

	c, err := okf.Parse(doc)
	if err != nil {
		panic(err)
	}
	fmt.Println(c.Extra["owner"])

	out := c.Bytes()
	reparsed, err := okf.Parse(out)
	if err != nil {
		panic(err)
	}
	fmt.Println(reparsed.Extra["owner"])
	fmt.Println(reparsed.Body == c.Body)
}
Output:
team:sre
team:sre
true

func (*Concept) Citations

func (c *Concept) Citations() []Citation

Citations returns the legacy v0.1 `# Citations` body list, if present. v0.2 producers should prefer `sources` frontmatter (Concept.Sources); this is a fallback for reading older documents (§13.1).

func (*Concept) FootnoteSourceIDs

func (c *Concept) FootnoteSourceIDs() []string

FootnoteSourceIDs returns the sources[].id values that are referenced by a markdown footnote (`[^id]`) in the body, sorted — OKF v0.2 §5.1 per-claim attribution. Unmatched footnotes (whose label has no corresponding sources[].id) are ignored, permissively.

func (*Concept) IsStale

func (c *Concept) IsStale(today Date) bool

IsStale reports whether the concept is stale per `stale_after` (OKF v0.2 §5.5): today >= StaleAfter. today is supplied by the caller — this package never calls time.Now. Returns false when StaleAfter is absent or was unparseable at parse time (a zero Date), matching the reference implementation's is_stale.

func (*Concept) LifecycleStatus

func (c *Concept) LifecycleStatus() string

LifecycleStatus returns the concept's lifecycle status (OKF v0.2 §5.4), defaulting to StatusStable when Status is absent. An unknown Status value passes through unchanged rather than being rejected or normalized.

func (c *Concept) Links() []Link

Links returns every markdown link in the concept's body, each flagged internal (bundle-relative) or external.

func (*Concept) TrustTier

func (c *Concept) TrustTier() string

TrustTier derives a concept's trust tier from Verified (OKF v0.2 §5.3):

  • no verification events => "unverified"
  • verified only by non-`human:` actors => "machine-confirmed"
  • verified by any `human:<id>` actor => "human-reviewed"
Example

ExampleConcept_TrustTier derives a concept's trust tier from a `verified` actor: any `human:` actor makes the concept human-reviewed.

package main

import (
	"fmt"

	okf "github.com/paultyng/go-okf"
)

func main() {
	c, err := okf.Parse([]byte(`---
type: Metric
title: Revenue
verified: { by: human:ahormati, at: 2026-06-25T09:00:00Z }
---

body
`))
	if err != nil {
		panic(err)
	}

	fmt.Println(c.TrustTier())
}
Output:
human-reviewed

func (*Concept) Typed

func (c *Concept) Typed() (any, bool)

Typed dispatches to the decoder registered for c.Type, if any. It returns (nil, false) when no decoder is registered for the type, or when the registered decoder returns an error — callers that need the error should call the registered decode func (or As[T]) directly.

type ConceptID

type ConceptID string

ConceptID is a concept's path within a bundle, with the `.md` suffix removed (OKF v0.2 §2), stored as its `/`-joined segments.

func ConceptIDFromPath

func ConceptIDFromPath(path string) ConceptID

ConceptIDFromPath permissively derives a concept id from a bundle-relative file path (e.g. "tables/events_.md" -> "tables/events_"), accepting whatever is on disk without segment validation.

func ParseConceptID

func ParseConceptID(s string) (ConceptID, error)

ParseConceptID strictly validates s as a concept id: every `/`-separated segment must match [A-Za-z0-9_][A-Za-z0-9_.\-]*. Use this to validate an id supplied by a caller (e.g. a link target); use ConceptIDFromPath for permissively deriving an id from whatever is actually on disk.

type Date

type Date struct {
	time.Time
}

Date is an ISO 8601 full-date (YYYY-MM-DD), used by `stale_after` (§5.5), `sources[].last_modified` (§5.1), and log headings (§9) — distinct from Actor.At, a full datetime. Parsing tolerates a leading date within a longer datetime string (the first 10 characters), matching the reference implementation's is_stale behavior.

func NewDate

func NewDate(year int, month time.Month, day int) Date

NewDate constructs a Date from year/month/day, matching time.Date's component semantics (UTC, midnight).

func ParseDate

func ParseDate(s string) (Date, error)

ParseDate parses a string as an ISO 8601 full-date, tolerating a leading date within a longer datetime string (first 10 characters).

func (Date) MarshalYAML

func (d Date) MarshalYAML() (any, error)

MarshalYAML implements yaml.Marshaler, emitting YYYY-MM-DD.

func (*Date) UnmarshalYAML

func (d *Date) UnmarshalYAML(node *yaml.Node) error

UnmarshalYAML implements yaml.Unmarshaler. It reads the node's literal scalar value directly (rather than node.Decode into a typed value) so that both plain string dates and YAML's implicitly-resolved !!timestamp scalars parse identically.

A syntactically-valid document with a value that isn't a parseable date (wrong kind, or a scalar like "not-a-date") must never fail Concept parsing — permissive parsing (OKF v0.2 §11) treats a bad optional date as absent rather than an error. Callers distinguish "absent" via Date.IsZero() (see Concept.IsStale).

type Executor

type Executor struct {
	Resource string   `yaml:"resource,omitempty"`
	Receipt  []string `yaml:"receipt,omitempty"`
}

Executor names how a computation is run and what a run must return.

type ExternalLink struct {
	URL     string // verbatim as first authored — never canonicalized.
	Origins []Origin
	Type    string // optional, from a resource/sources entry.
	Label   string // optional, from a title/sources entry.
}

ExternalLink is one external URL referenced anywhere in a bundle, deduplicated by CanonicalURL, with every discovery site recorded.

type Index

type Index struct {
	OKFVersion string
	Sections   []IndexSection
}

Index is a parsed (or synthesized) index.md: an untyped directory listing for progressive disclosure (OKF v0.2 §8). OKFVersion is only ever populated for a bundle-root index.md, the sole place frontmatter is permitted in an index.md (§12).

func ParseIndex

func ParseIndex(data []byte) (*Index, error)

ParseIndex parses an index.md's raw bytes. A bundle-root index.md may carry a leading YAML frontmatter block whose only recognized key is `okf_version`; any other index.md has no frontmatter.

func (*Index) Bytes

func (idx *Index) Bytes() []byte

Bytes renders the index back to markdown: a bundle-root okf_version frontmatter block (if set) followed by heading-delimited sections.

type IndexBuildEntry

type IndexBuildEntry struct {
	Type        string
	Title       string
	Link        string
	Description string
}

IndexBuildEntry is one concept to include when synthesizing an index.md section list via BuildIndexSections.

type IndexChildSummary

type IndexChildSummary struct {
	Title       string
	Description string
}

IndexChildSummary is the (title, description) pair passed to a Synthesizer describing one child (concept or subdirectory) of a directory being indexed.

type IndexEntry

type IndexEntry struct {
	Title       string
	Link        string
	Description string
}

IndexEntry is one bullet-list item in an index.md section (OKF v0.2 §8): `* [Title](Link) - Description`.

type IndexSection

type IndexSection struct {
	Heading string
	Entries []IndexEntry
}

IndexSection is one heading-delimited group of entries in an index.md.

func BuildIndexSections

func BuildIndexSections(entries []IndexBuildEntry) []IndexSection

BuildIndexSections groups entries by Type (an empty Type groups under "Other"), sorted by type name, with each section's entries sorted by title (case-insensitive) — mirroring the reference synthesizer's grouping and sort behavior.

type Link struct {
	Text     string
	Target   string
	External bool
}

Link is a markdown link found in a concept body (OKF v0.2 §6.1). External is false for a bundle-relative link (absolute "/..." or relative "./...", "../...").

type Log

type Log struct {
	Heading  string
	Sections []LogSection
}

Log is a parsed (or newly built) log.md: a flat, date-grouped, newest-first chronological history of changes (OKF v0.2 §9).

func ParseLog

func ParseLog(data []byte) (*Log, error)

ParseLog parses a log.md's raw bytes.

func (*Log) Bytes

func (l *Log) Bytes() []byte

Bytes renders the log back to markdown.

func (*Log) Insert

func (l *Log) Insert(entry LogEntry)

Insert adds entry to the log: finding or creating its date section (newest-first order among sections) and prepending the entry within that section (newest-first within a day). The date is supplied by the caller — this package never calls time.Now.

Example

ExampleLog_Insert adds an entry to a log.md, with the caller supplying the date so rendering stays deterministic.

package main

import (
	"fmt"
	"time"

	okf "github.com/paultyng/go-okf"
)

func main() {
	lg := &okf.Log{}
	lg.Insert(okf.LogEntry{
		Date: okf.NewDate(2026, time.May, 15),
		Kind: "Initialization",
		Text: "Created foundational directory structure.",
	})

	fmt.Print(string(lg.Bytes()))
}
Output:
# Directory Update Log

## 2026-05-15
* **Initialization**: Created foundational directory structure.

type LogEntry

type LogEntry struct {
	Date  Date
	Kind  string
	Text  string
	Links []Link
}

LogEntry is one bullet-list item in a log.md date section (OKF v0.2 §9). Kind is the leading bold word convention ("Update", "Creation", "Initialization", or any free-form word); it is empty when the entry has no leading bold word. Links is derived from Text, not stored.

type LogSection

type LogSection struct {
	Date    Date
	Entries []LogEntry
}

LogSection groups a log.md's entries under one date heading.

type Origin

type Origin struct {
	ConceptID string
	Source    SourceKind
}

Origin records one site where an ExternalLink was discovered.

type Parameter

type Parameter struct {
	Name     string `yaml:"name"`
	Type     string `yaml:"type"`
	Required bool   `yaml:"required"`
}

Parameter is a typed, named hole an Attested Computation's computation may bind (OKF v0.2 §10.2).

type Source

type Source struct {
	ID           string       `yaml:"id,omitempty"`
	Resource     string       `yaml:"resource"`
	Title        string       `yaml:"title,omitempty"`
	Author       string       `yaml:"author,omitempty"`
	UsageCount   int          `yaml:"usage_count,omitempty"`
	LastModified *Date        `yaml:"last_modified,omitempty"`
	UsageWindow  *UsageWindow `yaml:"usage_window,omitempty"`
}

Source records a material a concept derives from (OKF v0.2 §5.1).

type SourceKind

type SourceKind int

SourceKind identifies which channel discovered an external link.

const (
	// SourceResource is the frontmatter `resource:` field.
	SourceResource SourceKind = iota
	// SourceProvenance is a `sources[]` frontmatter entry (§5.1).
	SourceProvenance
	// SourceCitation is a legacy body `# Citations` entry (§13.1).
	SourceCitation
	// SourceInlineLink is an ordinary body markdown link.
	SourceInlineLink
)

func (SourceKind) String

func (k SourceKind) String() string

String returns the lowercase channel name: "resource", "sources", "citation", or "inline-link" (or "unknown" for an out-of-range value).

type Synthesizer

type Synthesizer func(dir string, children []IndexChildSummary) string

Synthesizer produces a directory's own summary description from its children, for use as that directory's entry in its parent's index. It is only invoked when a directory has more than one child, or one child with no description of its own (go-okf runs no LLM and no code: this is entirely caller-supplied).

type UsageWindow

type UsageWindow struct {
	From *Date `yaml:"from,omitempty"`
	To   *Date `yaml:"to,omitempty"`
}

UsageWindow frames a source's usage_count with a date range (OKF v0.2 §5.1). Written once as a sibling of `sources` (Concept.UsageWindow); a single Source entry MAY carry its own UsageWindow to override the shared one.

type Validator

type Validator interface {
	Validate() []Violation
}

Validator is the behavioral opt-in for types that contribute custom conformance rules (see Bundle.Conformance). It is deliberately not part of the registry contract: a registered type only needs to implement it when it has extra rules to enforce.

type Violation

type Violation struct {
	ConceptID string
	Rule      string
	Detail    string
}

Violation is one conformance finding (OKF v0.2 §11). ConceptID is filled in by Bundle.Conformance when a Validator implementation leaves it empty, so individual Validate() implementations don't need bundle context.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL