OKF4net Coderise
winget install --id=Coderise.OKF4net -e Zero-dependency .NET implementation of the Open Knowledge Format (OKF) v0.1 -- parse, validate, index, and graph OKF knowledge bundles.
winget install --id=Coderise.OKF4net -e Zero-dependency .NET implementation of the Open Knowledge Format (OKF) v0.1 -- parse, validate, index, and graph OKF knowledge bundles.
A zero-dependency .NET (C#) implementation of the Open Knowledge Format (OKF) v0.2 ā Google's open, human- and agent-friendly format for representing knowledge as a directory of markdown files with YAML frontmatter.
> OKF is intentionally minimal: "if you can cat a file, you can read OKF; if
> you can git clone a repo, you can ship it." This project honors that
> spirit ā it is implemented entirely on the .NET base class library, with
> no third-party dependencies (it includes its own YAML-subset parser,
> markdown link scanner, directory walker, and CLI argument parsing).
>
> OKF4net is an independent, zero-dependency .NET implementation of the Open
> Knowledge Format, built from the OKF v0.2 specification. It is backed by an
> extensive test suite, including byte-exact golden CLI comparisons (see
> tests/fixtures/). For the full derivation and
> attribution chain, see NOTICE.
š Documentation & project site ā jchable.github.io/okf4net ā a guided project overview, getting-started walkthroughs, and developer docs: getting started Ā· guides Ā· CLI reference Ā· library reference Ā· MCP Ā· spec mapping. This README is the technical reference; the site is the friendlier entry point for newcomers.
> Want to contribute? OKF4net is a young, welcoming project with a clear
> roadmap and issues labelled
> good first issue.
> No prior OKF knowledge required ā see Contributing & roadmap.
---, followed by a markdown body..md removed
(tables/users.md ā tables/users)./tables/users.md, bundle-relative) or relative (./other.md).index.md files provide directory listings for progressive disclosure;
log.md files record date-grouped change history. Both are reserved
filenames.type field on
every concept; consumers must otherwise be permissive (unknown types, unknown
keys, broken links, and missing optional fields are all tolerated).See mapping to the spec below for the section-by-section mapping, or the longer What OKF is page on the site.
OKF4net ships as several projects. The core library is the foundation; each other project layers a specific integration on top and points back to it.
| Project | NuGet package | Responsibility | Deep dive |
|---|---|---|---|
OKF4net | OKF4net | Zero-dependency core library: parse, validate, index, graph OKF bundles. | Library overview |
OKF4net.Cli | ā (Native AOT okf binary, no PackageId) | The okf command-line tool (validate/info/index/graph/parse/fmt/render). | As a CLI |
OKF4net.Viewer | ā (ships inside the okf binary, not packed by release.yml) | Static HTML site generation for a bundle; backs the okf render verb. | As a CLI |
OKF4net.Agents | OKF4net.Agents | Microsoft Agent Framework tools + OkfContextProvider (context & memory). | Microsoft Agent Framework |
OKF4net.Catalog | OKF4net.Catalog | Local catalog of OKF bundles: catalog.json manifest + source resolver. | Local catalog Ā· README |
OKF4net.Catalog.Hosting | OKF4net.Catalog.Hosting | IServiceCollection integration (AddKnowledge) for the catalog. | README |
OKF4net.Mcp | OKF4net.Mcp | Local MCP server exposing an OKF bundle to Claude Desktop / Claude Code. | Use OKF in Claude (MCP) Ā· README |
OKF4net.Attestation | OKF4net.Attestation | Host-plugged §10 attested-computation orchestration (bind ā execute ā attest). | Attested computation Ā· README |
| Type / namespace | Responsibility |
|---|---|
OKF4net.Yaml.YamlValue / YamlMapping | A YAML-subset value/mapping model for frontmatter |
OKF4net.Yaml.YamlValue.Parse / YamlEmitter | Parser entry point and emitter for the same YAML subset |
OKF4net.OkfDocument | Frontmatter + body; parse / serialize / validate (§4) |
OKF4net.Frontmatter | Typed accessors over an order-preserving mapping (§4.1) |
OKF4net.ConceptId | ConceptId ā path conversion and segment validation (§2) |
OKF4net.Actor / Trust / Provenance / Lifecycle | Provenance, trust, and lifecycle value types and parsing (§5, §7) |
OKF4net.LinkScanner | Markdown link extraction, classification, legacy citations (§6.1, §13.1) |
OKF4net.Bundle | Bundle.Load ā walk a tree, build the concept graph + backlinks (§3, §6) |
OKF4net.IndexGenerator | Generate index.md directory listings (§8) |
OKF4net.ChangeLog | Parse / build log.md update histories (§9) |
OKF4net.BundleValidator | §11 conformance checking with severity-tagged diagnostics |
The split follows the OKF reference implementation's bundle/ package
(document.py, index.py, paths.py) so behaviour stays spec-compatible:
the document parser, validator, and index generator are verified by an
extensive test suite, including byte-exact golden CLI comparisons.
Frontmatter keeps the full
ordered mapping and layers typed getters (Type, Title, Tags, ā¦) on
top. This satisfies the spec's requirement that consumers preserve unknown
keys when round-tripping.Bundle.Load never aborts on a bad concept file; it
collects parse failures in ParseErrors and keeps going. Broken
cross-links are retained as graph edges to non-existent concepts.OkfDocument.ValidateConformance() enforces
only what §11 requires (a non-empty type). OkfDocument.Validate() matches
the stricter producer-side check from the reference agent (type, title,
description, timestamp).|/> block scalars, and comments; it rejects (with a clear error)
the YAML features that never appear in frontmatter ā anchors, tags, multiple
documents.A concern-by-concern API walkthrough lives in the library docs on the site; below is the short version.
using OKF4net;
var bundle = Bundle.Load("./my_bundle");
Console.WriteLine($"{bundle.Count} concepts");
// Conformance check (§11).
var report = BundleValidator.Validate(bundle);
if (report.IsConformant)
{
Console.WriteLine($"conformant with OKF v{OkfSpec.Version}");
}
// Traverse the cross-link graph.
var id = ConceptId.Parse("tables/orders");
foreach (var link in bundle.LinksFrom(id))
{
Console.WriteLine($"{id} -> {link.Target} (exists: {link.Exists})");
}
foreach (var backlink in bundle.Backlinks(id))
{
Console.WriteLine($"cited by {backlink}");
}
Parsing and round-tripping a single document:
using OKF4net;
var doc = OkfDocument.Parse("---\ntype: Metric\ntitle: DAU\n---\n\n# Body\n");
Console.WriteLine(doc.Frontmatter.Type); // "Metric"
doc.ValidateConformance(); // throws DocumentValidationException on failure
// Serialize() preserves frontmatter key order and the body.
var text = doc.Serialize();
On Windows, install via winget:
winget install Coderise.OKF4net
On any OS, build from source ā see Building & testing.
okf validate Check a bundle against OKF v0.2 conformance (§11)
okf audit Report trust, freshness and lifecycle across the bundle
okf info Summarize a bundle (concepts, types, links, version)
okf index (Re)generate every index.md in the bundle
okf graph Print the cross-link graph (--dot for Graphviz DOT)
okf parse Parse one concept document and print its structure
okf fmt Normalize a document by parse + re-serialize (-w writes)
okf render --out Generate a browsable HTML site from a bundle
Every verb takes -h/--help for its own usage and option list. Arguments are
validated per verb: an option that verb does not define, or a surplus
positional, is an error rather than silently ignored ā so a typo'd flag never
runs the command with different behaviour than you asked for.
okf validate exits non-zero when a bundle is not conformant, so it drops
straight into CI:
okf validate ./bundles/ga4
okf graph ./bundles/ga4 --dot | dot -Tsvg > graph.svg
okf audit reports trust, freshness and lifecycle across a whole
bundle: counts per trust tier (§5.3) and status (§5.4), plus the worklist of
stale concepts (§5.5). Filter it to ask corpus-level questions ā
# Which concepts are past stale_after and were never verified by a human?
okf audit bundles/acme_retail --stale --trust unverified,machine-confirmed
Without filter flags it selects exactly what --stale selects and prints the
summary form; with any filter flag it prints one line per matching concept, so
the output pipes. --json always emits the full document.
--as-of pins the date staleness is evaluated against, on both
okf audit and okf validate; it pins to midnight UTC on that date, since §5
makes stale_after an instant. Without it, anything touching stale_after
(§5.5) depends on the day it runs ā including okf validate's
concept is stale warning, which is why a CI job that wants a reproducible
verdict should pin the date rather than let the calendar move under it. Note the counts
always cover the whole bundle while findings covers the selection: audit is
a worklist, not an inventory (use okf info --json for that).
Generate a browsable HTML site from a bundle:
okf render bundles/ga4 --out /tmp/ga4-site
# then open /tmp/ga4-site/index.html
The generated site is self-contained and opens straight off the filesystem ā
no server needed. It is read-only; full-text search arrives with the planned
okf serve companion.
okf is OKF4net.Cli, published as a self-contained, Native AOT
single-file binary ā no .NET runtime installation required on the target
machine. Full command reference with real output samples:
CLI docs on the site.
src/OKF4net.Agents/ exposes bundle operations as function tools for the
Microsoft Agent Framework:
OkfBundleTools wraps one bundle root and its GetTools() method returns
eleven ready-to-use AITools unconditionally, which AsAIAgent turns into an
agent's tool list, plus a twelfth ā okf_run_computation ā only when the
tool set is constructed with an OKF4net.Attestation orchestrator wired in
(see Attested computation).
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OKF4net.Agents;
IChatClient chatClient = /* your IChatClient, e.g. from an OpenAI/Azure client */;
var tools = new OkfBundleTools("./my_bundle");
// The write tools need the host's approval before they run. `GetTools()` with
// no argument returns them ungated ā see the security note below.
AIAgent agent = chatClient.AsAIAgent(tools: tools.GetTools(OkfToolMode.RequireApprovalForWrites));
var response = await agent.RunAsync("Search the bundle for concepts about refunds.");
Console.WriteLine(response.Text);
The eleven unconditional tools, plus the twelfth conditional on an attestation orchestrator being wired (read ā browse ā graph ā search ā audit ā write ā append ā regenerate ā validate ā changes-since ā get-computation ā run-computation):
| Tool | Description |
|---|---|
okf_read_concept | Read one concept from the OKF bundle: its frontmatter, body, outgoing links and backlinks. |
okf_browse | Browse the bundle via its index files (progressive disclosure). Without a path, lists the bundle root. |
okf_graph | Inspect the cross-link graph. With a concept id: its outgoing links, backlinks and broken links. Without: bundle-wide stats. |
okf_search | Full-text search across concept titles, descriptions, tags and bodies. Returns matching concept ids ranked by relevance. |
okf_audit | Audit the bundle's trust, freshness and lifecycle signals (§5.3ā§5.5): counts by trust tier and status, plus the concepts needing attention. Read-only. |
okf_write_concept | Create or update a concept document. The frontmatter must contain non-empty type, title and description (producer-grade validation is enforced before writing). |
okf_append_log | Append an entry to the bundle root log.md under today's date (ISO). Note: log.md is re-rendered through the strict §9 model, so non-conforming prose or comments in a hand-authored log.md are not preserved. |
okf_regenerate_indexes | Regenerate every index.md in the bundle (progressive-disclosure listings). Run after adding or changing concepts. |
okf_validate_bundle | Validate the bundle against OKF v0.2 conformance (§11). Returns the diagnostics report. |
okf_changes_since | Summarize bundle changes since a given ISO date, aggregated from every log.md in the bundle. |
okf_get_computation | Read a §10 attested-computation concept's contract and sanctioned computation source. Always available; read-only, needs no attestation runtime. |
okf_run_computation | Run a §10 attested computation end to end (bind ā execute ā attest ā stale-gate) through a host-wired AttestationOrchestrator. Only present in GetTools() when one was passed to the constructor. |
Security note: bundle content (concept bodies, frontmatter, log entries)
is untrusted ā it comes from files on disk that may have been written by
another agent or a human contributor ā and is never injected into the
conversation with a system role; it only ever reaches the model as tool
output.
That matters most for the three write-capable tools (okf_write_concept,
okf_append_log, okf_regenerate_indexes), because an injection carried in a
concept body is only dangerous if it can reach a persistent write.
GetTools() returns them ungated, and nothing asks on your behalf: the
Agent Framework's approval mechanism is not active by default, so a plain
AIFunction is invoked directly. Choose how they are exposed:
// The model must not write at all:
var tools = okf.GetTools(OkfToolMode.ReadOnly);
// Or: every tool, but a write needs the host's approval first.
var tools = okf.GetTools(OkfToolMode.RequireApprovalForWrites);
RequireApprovalForWrites wraps exactly the write tools in
ApprovalRequiredAIFunction; read tools stay ungated, since prompting for
everything trains a user to click through and is how the one approval that
mattered gets waved past. OkfBundleTools.WriteToolNames is the single source
of truth for which tools count, so a write tool added later cannot slip past a
host's own filtering either. The parameterless GetTools() keeps its
historical ungated meaning so existing hosts are not changed under them.
The core OKF4net library stays dependency-free (BCL only); only
OKF4net.Agents references Microsoft.Agents.AI (see
Hard rules for the per-project dependency policy).
OkfContextProvider is an AIContextProvider that, layered onto the same
OkfBundleTools instance as the tools above, automatically injects relevant
bundle context into each invocation and ā when explicitly enabled ā captures
the exchange back into the bundle as long-term memory, no extra tool calls
required from the model. Register it via ChatClientAgentOptions.AIContextProviders
(the tools + providers convenience overload doesn't exist; this is the one
API surface that wires both):
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OKF4net.Agents;
var tools = new OkfBundleTools("./my_bundle");
// MemoryCapture defaults to MemoryCaptureMode.Disabled; opt in explicitly
// (see the memory trust model caveat below) to get the capture behavior
// shown here.
var provider = new OkfContextProvider(tools, new OkfContextProviderOptions { MemoryCapture = MemoryCaptureMode.Enabled });
AIAgent agent = chatClient.AsAIAgent(new ChatClientAgentOptions
{
ChatOptions = new ChatOptions { Tools = tools.GetTools(OkfToolMode.RequireApprovalForWrites) },
AIContextProviders = [provider],
});
var response = await agent.RunAsync("What do we know about orders?");
OkfContextProviderOptions:
| Option | Default | Meaning |
|---|---|---|
TokenBudget | 2000 | Approximate token budget (chars/4 estimate) for context injected per invocation. |
MemoryCapture | MemoryCaptureMode.Disabled | Opt-in: MemoryCaptureMode.Enabled captures exchanges as long-term memory concepts in the bundle after each invocation; Disabled writes nothing. |
MemoryDirectory | "memory" | Bundle subdirectory holding memory concepts, as a single ConceptId segment (no /). |
MaxConceptsInjected | 5 | Maximum number of scored concepts injected into a single invocation's context. |
OnInternalError | null | Host-side sink for exceptions context assembly swallows (a failed bundle load, a failed knowledge/memory read). The model only ever sees a category. |
Security note: as with the tools above, bundle content is untrusted.
ProvideAIContextAsync injects the bundle root index plus the top scored
concepts (progressive disclosure, budget-bounded) as reference data in a
message ā it is never written into AIContext.Instructions, so a
prompt-injection payload smuggled into a concept body cannot reach the
instructions channel.
Information flows the other way too. When context assembly fails, the model is
told a category (bundle unavailable: I/O error), never the exception's own
message ā a .NET filesystem exception carries the absolute path, and an
exception from a host-plugged runtime can carry a connection string or a query.
The same applies to okf_run_computation: the outcome rendered to the model
names the failing stage and the exception type, while the exception itself
stays on AttestationOutcome.Error for the host. Wire OnInternalError to get
the detail into your own logs.
Memory design (v1, deterministic): StoreAIContextAsync captures each
exchange with no LLM call ā the last user message and the agent's final
response are appended to one memory concept per UTC day
(/), plus a matching log.md entry. Captured
text is blockquote-neutralized (each line prefixed with >) so injected markdown
structure (---, headings, a fake # Citations section) can't be mistaken
for genuine document structure. Writes go through the same
OkfBundleTools.WriteConcept/AppendLog calls ā and therefore the same
producer-grade validation, write lock and reparse-point guards ā any other
caller would use, and the provider never throws toward the invocation
pipeline. The write lock and the reparse-point guards have precise scopes ā
see the concurrency and reparse-point caveats below before relying on either
as a stronger guarantee than documented.
A few known v1 caveats:
TokenBudget uses a crude chars/4 estimate, and
the per-block `` framing overhead (tags, id, joining newlines,
a trailing truncation marker) is charged against it, so the injected
message tracks the budget closely ā but it's still a soft budget, not a
hard cap: the estimate itself is approximate, so the result can land a
little under or over.fences are readability markers, not a security boundary:** the whole injected message is untrusted user-role reference data (a concept body containing a literal could visually
break out of its fence); this doesn't matter because nothing in that
message is ever treated as instructions in the first place (see the
security note above).ProvideAIContextAsync
can surface one session's captured exchange in a completely different
session sharing the same bundle. That's why MemoryCapture defaults to
MemoryCaptureMode.Disabled ā set it to MemoryCaptureMode.Enabled
only for a bundle that's intended to be a shared, non-sensitive memory
across those sessions.OkfBundleTools.AppendToConceptAtomic under a write lock that's shared by
every OkfBundleTools instance pointed at the same canonicalized bundle
path ā not just one instance ā via a process-wide registry keyed on the
resolved bundle root. So two (or more) truly concurrent
StoreAIContextAsync calls, even across separate OkfBundleTools/
OkfContextProvider instances sharing a session pool, never lose a
same-day section as long as they're all in the same process. This
guarantee does not extend across separate processes (e.g. two CLI
invocations, or two independently-hosted server processes sharing a
network bundle path) ā nothing coordinates them, so a same-day count
divergence between log.md and the memory concept is possible there.
Separately, the reparse-point guard that write tools use to reject a
symlink/junction inside the bundle is a check-then-write: it rejects a
reparse point present when it runs (both an early check and a second,
best-effort re-check immediately before the actual write), but a
concurrent local actor able to substitute a path component with a
symlink/junction in the narrow remaining window is not something a C#
lock ā in-process or not ā can fully close (there's no portable
no-follow atomic write in .NET). That actor would already need write
access inside the bundle tree to plant the substitution in the first
place, so this residual gap defends the bundle's own content from causing
an accidental escape more than it defends against a hostile, already
co-resident writer.src/OKF4net.Attestation/ orchestrates §10 Attested
Computations:
a concept can declare a runtime/parameters/computation/executor/attester
contract (Frontmatter.ComputationContract) and a sanctioned computation ā
an inline fenced # Computation block or a computation: file resolved via
§6.2 path-safe resolution (OkfDocument.Computation()). The host plugs in
IParameterBinder, IComputationExecutor and IAttester per runtime name
through an IAttestationRuntimeRegistry; AttestationOrchestrator.RunAsync
drives one run end to end ā resolve ā bind ā execute ā receipt-shape check ā
attest ā gate on the verdict and stale_after ā always returning an
AttestationOutcome (errors-as-data, never throwing for an expected
failure). §10.6: a verdict is never written back to the bundle ā attestation
is per-run, not stored provenance.
using OKF4net;
using OKF4net.Attestation;
IAttestationRuntimeRegistry runtimes = new AttestationRuntimeRegistry(
new Dictionary { ["bigquery"] = myBigQueryRuntime });
var orchestrator = new AttestationOrchestrator(runtimes);
AttestationOutcome outcome = await orchestrator.RunAsync(
bundle, conceptId, new Dictionary { ["region"] = "eu" });
if (outcome.Displayable)
{
Console.WriteLine(outcome.Receipt);
}
else
{
Console.WriteLine(string.Join("; ", outcome.Reasons));
}
OKF4net.Agents' okf_get_computation tool (read-only, always available)
surfaces a computation's contract and source without running anything; pass
an AttestationOrchestrator to new OkfBundleTools(bundleRoot, orchestrator) to also expose okf_run_computation ā see the tool
table above. OKF4net.Attestation
references only OKF4net ā zero third-party runtime dependencies. See
OKF4net.Attestation's README for the
full contract/value-type reference.
src/OKF4net.Catalog/ and src/OKF4net.Catalog.Hosting/ add a catalog of
local OKF bundles: a hot-reloadable catalog.json manifest naming one or more
bundles as sources, and a resolver that searches every enabled source.
catalog.json is an OKF4net manifest, not an OKF concept ā it configures
the catalog from the outside and is not part of the OKF spec.
using OKF4net.Catalog;
using OKF4net.Catalog.Hosting;
services.AddKnowledge(o => o.AddCatalogFile("./config/catalog.json"));
// Elsewhere, resolve and search:
IKnowledgeResolver resolver = provider.GetRequiredService();
KnowledgeContext result = await resolver.SearchAsync(new KnowledgeQuery("refund policy"));
V1 limits, stated exactly:
Scoped memory (shipped): a read-only knowledge vs writable memory
source role split, and host-scoped, layered memory tiers (session / user /
tenant) so captured memory can be enabled on a multi-user deployment without
cross-scope leakage ā see
the scoped-memory design
for the full reasoning and
OKF4net.Catalog's README
for the deployment example.
Cross-source ranking (shipped): three selectable resolver strategies ā
GroupedBySource (the default, unchanged behaviour), Merged (one ranking
by descending score across every source), and PriorityWeighted (source
priority first, score within a tier) ā chosen per host or per query, with
optional fairness interleaving for budget-truncated consumers. See
the resolver-strategies design
and OKF4net.Catalog's README.
Source visibility (shipped): restrict which sources a caller may see,
per host default or per query ā a host-precomputed PermittedSourceIds set
(the recommended default) or a SourceVisibilityPolicy function evaluated
per source, either overridable per query. See
the source-visibility design
and OKF4net.Catalog's README.
See OKF4net.Catalog and OKF4net.Catalog.Hosting for full package documentation.
OKF4net.Mcp is a local MCP server that plugs an OKF bundle straight into
Claude Desktop / Claude Code, so you can read, search, and persist knowledge in
your bundle from a chat ā the way an Obsidian MCP server exposes a vault.
dotnet tool install -g OKF4net.Mcp
Then point Claude Desktop at a bundle in claude_desktop_config.json:
{ "mcpServers": { "okf": { "command": "okf-mcp", "args": ["/path/to/bundle"] } } }
okf-mcp serves the bundle read-only by default; set OKF_MCP_WRITABLE=1
to register the three write tools as well. See
src/OKF4net.Mcp/README.md for the full tool list, or the
MCP setup guide on the site.
This table is also published as the spec-mapping page on the site.
| Spec section | Implemented by |
|---|---|
| §2 Terminology / concept id | OKF4net.ConceptId |
| §3 Bundle structure | OKF4net.Bundle, Bundle.ReservedFilenames |
| §4 Concept documents | OKF4net.OkfDocument, OKF4net.Frontmatter |
| §4.2 Body headings | OkfDocument.Computation() (fenced # Computation heading) |
| §5 Provenance, trust, and lifecycle | Frontmatter.Sources/Generated/Verified/TrustTier/Status/StaleAfter, Actor/Trust/Provenance/Lifecycle |
| §5.3ā§5.5 trust, lifecycle, staleness | ConceptAudit, AuditQuery, AuditReport ā the corpus-level query behind okf audit and okf_audit |
| §6 Cross-linking and paths | OKF4net.LinkScanner, Bundle.LinksFrom / Bundle.Backlinks |
| §6.2 Path-valued fields | OkfDocument.FrontmatterResources(), Bundle.TryResolveResource / Bundle.ReadResourceText |
| §7 Actor convention | OKF4net.Actor.Parse ā human:/process:// |
| §8 Index files | OKF4net.IndexGenerator |
| §9 Log files | OKF4net.ChangeLog |
| §10 Attested Computation | Frontmatter.ComputationContract, OkfDocument.Computation(), OKF4net.Attestation (AttestationOrchestrator) |
| §11 Conformance | OKF4net.BundleValidator |
| §12 Versioning | Bundle.OkfVersion, OKF4net.OkfSpec.Version |
| §13 Changes from v0.1 (legacy fallbacks) | Frontmatter.LastChangedAt (falls back to legacy timestamp), OkfDocument.Sources() (falls back to a legacy # Citations list) |
| OKF4net | OKF spec | Highlights |
|---|---|---|
| 0.1.0 | v0.1 | Core library + okf CLI (validate/info/index/graph/parse/fmt), Native AOT |
| 0.1.1 | v0.1 | winget distribution; project website and developer docs |
| 0.2.0 | v0.1 | OKF4net.Agents (Agent Framework tools + context provider), OKF4net.Catalog(.Hosting), OKF4net.Mcp server, scoped long-term memory (V2) |
| 0.3.0 | v0.2 | Provenance/trust/lifecycle frontmatter model, v0.1 legacy-field fallbacks, v0.2 validator diagnostics |
| 0.3.1-preview.1 | v0.2 | Per-caller source visibility, §10 Attested Computation (new OKF4net.Attestation package, okf_get_computation/okf_run_computation), §6.2 path-valued frontmatter resolution |
| 0.4.0 | v0.2 | okf-mcp bundle auto-discovery, OkfBundleTools.WriteToolNames, ComputationExtractor fence-safety fix, path-containment comparison hardening |
| 0.5.0 | v0.2 | --json diagnostics on validate/info, §11 conformance now enforced for malformed reserved files, YAML multi-line scalar support, producer-facing in-memory concept API |
Contributions are welcome and the barrier to entry is deliberately low ā the library is pure BCL C# with no third-party runtime dependencies, so there is no framework to learn before you can help.
ROADMAP.md.help wanted.CONTRIBUTING.md.dotnet build OKF4net.sln # core library + okf CLI + test project
dotnet test OKF4net.sln # unit + integration tests (incl. golden CLI comparisons)
dotnet publish src/OKF4net.Cli -c Release # Native AOT, self-contained okf binary
Just want the okf binary on Windows, not a source build? winget install Coderise.OKF4net (see As a CLI).
OKF4net is licensed under the GNU Lesser General Public License v3.0 or
later (LGPL-3.0-or-later) ā see LICENSE for the full LGPLv3
text and LICENSE.GPL-3.0 for the GPLv3 text it
incorporates by reference.
This is a derivative work: its document parser, concept-id conventions, and
index generator derive from the Apache-2.0-licensed
OKF reference implementation
by Google LLC. Portions derived from that and prior upstream work remain
subject to the Apache License, Version 2.0 ā see
LICENSE.Apache-2.0. Full attribution, including the
complete derivation chain, is in NOTICE.
This is an independent implementation and is not affiliated with or endorsed by Google.