docs/guides.mdtype: Guide

Recipes for real tasks.

Short, task-shaped walkthroughs — traverse a graph, gate a build, regenerate listings, normalize a file, ship the binary. For the exhaustive surface, see library.md and cli.md.

##

Traverse the cross-link graph

§5 — LinksFrom · Backlinks

Load once, then walk edges in either direction. Broken links stay in the graph so you can find every hole in one pass.

using OKF4net;

var bundle = Bundle.Load("./my_bundle");
var id = ConceptId.Parse("tables/orders");

// Outgoing — each link knows whether its target exists.
foreach (var link in bundle.LinksFrom(id))
    Console.WriteLine($"{id} -> {link.Target} (exists: {link.Exists})");

// Incoming — who cites this concept.
foreach (var back in bundle.Backlinks(id))
    Console.WriteLine($"cited by {back}");

// Every dangling edge in the whole bundle.
foreach (var (source, rawTarget) in bundle.BrokenLinks())
    Console.WriteLine($"{source} -x {rawTarget}");
##

Gate CI on conformance

§9 — exit codes

okf validate exits non-zero on a non-conformant bundle. The binary is self-contained, so a runner needs no .NET installed — copy the file and run it.

# .github/workflows/knowledge.yml
name: Validate knowledge
on: [push]
jobs:
  okf:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./okf validate ./bundles/ga4

Prefer to gate from your own tool? The library reports the same result — warnings never fail conformance, only errors do:

var report = BundleValidator.Validate(Bundle.Load("./bundles/ga4"));
Environment.Exit(report.IsConformant ? 0 : 1);
##

Regenerate index.md listings

§6 — progressive disclosure

After adding or renaming concepts, rewrite every directory listing. The call returns the paths it wrote.

var written = IndexGenerator.RegenerateIndexes("./my_bundle");
foreach (var path in written)
    Console.WriteLine($"wrote {path}");

Same thing from the shell: okf index ./my_bundle. Supply your own description synthesizer with RegenerateIndexesWith(root, synthesize) when the default summaries aren't enough.

##

Read a change log

§7 — log.md

Bundle.LogFiles lists every reserved log.md; ChangeLog.Parse turns one into date-grouped entries.

using OKF4net;

foreach (var logPath in bundle.LogFiles)
{
    var log = ChangeLog.Parse(File.ReadAllText(logPath));
    foreach (var day in log.Days)
        Console.WriteLine($"{day.Date}: {day.Entries.Count} entr(y/ies)");
}
##

Normalize a document

§4 — the round-trip guarantee

Parse and re-serialize to normalize frontmatter and block structure. Unknown keys come out untouched — the ordered mapping is preserved, not projected onto a fixed type.

var doc = OkfDocument.Parse(File.ReadAllText("orders.md"));
File.WriteAllText("orders.md", doc.Serialize());

Or in place from the shell: okf fmt orders.md -w.

##

Publish the AOT binary

no runtime on the target

Build okf as a self-contained, single-file Native AOT executable — nothing to install where it runs.

$ git clone https://github.com/jchable/okf4net
$ dotnet publish src/OKF4net.Cli -c Release   # self-contained okf binary

cli.md — every command and flag · library.md — the full API