Skip to content

Repository files navigation

OKF Enforcer

Build Release License

An Obsidian plugin that validates and enforces the Open Knowledge Format (OKF) v0.2 across your vault — keeping every note self-describing, agent-readable, and portable.

OKF is an open, minimal convention for representing knowledge as a directory of Markdown files with YAML frontmatter. Its one hard rule: every non-reserved note carries a parseable frontmatter block with a non-empty type. v0.2 adds first-class provenance, trust, lifecycle, and attestation on top of that, while staying backward-compatible with v0.1 bundles. This plugin makes following the format effortless. See the OKF specification.

Features

  • Conformance validation. Checks every note against OKF v0.2. The hard rules (parseable frontmatter, non-empty type, valid index.md/log.md structure — §11/§8/§9) are reported as errors; the spec's recommended fields and SHOULD-guidance are warnings you can toggle. The spec's permissive rules are respected — broken links and missing optional fields never fail a bundle.
  • Trust & provenance (v0.2). Opt-in checks for the §5 families: generated/verified and the actor convention, status (draft|stable|deprecated), stale_after — both that it's an absolute date and whether it has passed, so a note that's due for review says so — and sources with its credibility signals (author/usage_count/last_modified). The note's derived trust tier (unverified / machine-confirmed / human-reviewed) is shown in the status-bar tooltip.
  • Attested Computation (v0.2). Validates type: Attested Computation concepts (§10) — a required runtime, a present computation (inline # Computation fence or a computation path), and parameters/executor/attester shape.
  • v0.1 → v0.2 migration. A command rewrites a legacy timestamp into generated: { by, at } and lifts a body # Citations list into sources, then offers to declare okf_version: "0.2" in the root index.
  • Vault-wide report. A compact, collapsible side panel lists every non-conformant note grouped by the folder it sits in, errors first at both levels, with a one-line summary of conformant / error / warning counts. The folder is named once in its group header, so the rows under it read as file names rather than as the same path prefix repeated down the pane. The note you have open gets its own section at the top, listed open — so opening a note shows what is wrong with it without hunting the list for its row, and without a vault scan having run at all. Hidden by default; opens only on demand.
  • Status-bar indicator. A single status-bar item shows the active note's state ( / / ) with details in its tooltip — including the note's derived trust tier, when trust checks are on. Click it to auto-fix the current note.
  • Auto-fix. Inserts missing frontmatter (type, title, generated) non-destructively — it never overwrites values you've set.
  • Prompt for required fields. When a note is missing a meaningful type, a dialog lets you set type, title, and description directly.
  • On-save & on-create hooks. New notes, edited notes, and notes added by the Importer plugin are brought into conformance automatically.
  • index.md generation. §8 says an index may appear in a directory and §11 forbids failing a bundle for a missing one — so by default the plugin writes one for every folder rather than flagging what's absent, an empty or newly created folder included, and validates against §8 any index that already exists. A folder with nothing to list gets an empty index rather than a listing that describes emptiness; Obsidian's config folder and anything under Excluded folders are left alone. Generating over an existing index is additive: the entries it doesn't already list are appended, a link that points at the wrong path is corrected, an entry whose note the folder no longer holds is dropped, and your prose, ordering, titles, and edited descriptions stay as written. An index hand-written in Obsidian's own [[wikilink]] syntax, or as a numbered list, is read as already listing what it links at, and left in that shape; an entry that links at a heading (paxos.md#simple) keeps its fragment, and a heading you added keeps its place even once the entries under it are gone. Listings follow §8 (with okf_version in the root index): entries are grouped by their type# Concepts, # Metrics, # Attested Computations — so a listing says what a directory holds rather than only that it holds something. Notes carry their frontmatter description, as §8 recommends; a note whose type is missing is listed under # Untyped rather than assumed to be a concept, and attachments are listed under # Files. Subdirectory entries always link to that folder's own index.md, never a bare folder/ path that Obsidian would turn into a new note, and can pull their description from a named section (e.g. # Purpose) of that index. Because every folder has an index, no entry ever points at a file that isn't there.
  • Index gaps, reported rather than written (opt-in). For a vault whose index.md files are kept by hand — its own headings, its own order, its own groupings — generation writes a shape the vault didn't choose. Set Incomplete index.md to Report in the vault scan instead: a vault scan then warns where a folder has no index.md, and where an existing one doesn't list a note anywhere in the file, and writes nothing. A note counts as listed wherever it appears, so a listing you maintain yourself never reads as incomplete just for not looking generated. Opening a folder's index.md reports the same gaps in the pane's active-note section and in the status bar, so the note in front of you says what a scan would.
  • log.md entries. Adds dated §9 changelog entries.
  • Portent layer (opt-in, beta). Optionally layer the Portent knowledge-base spec on top of OKF — type vocabulary, lifecycle, and belongs_to/related_to relationships — surfaced as non-blocking warnings. The schema is fully free-form: rename fields (e.g. statusstate), redefine the accepted vocabularies, and choose which checks run, so you can match your own conventions or track the evolving pre-1.0 spec.
  • Large-vault friendly. Scans and fixes run through a batched, non-blocking queue with an inline progress bar — the UI never freezes.

Usage

Open the command palette and search for OKF:

Command What it does
Validate vault (full report) Scan everything and open the report panel
Validate active note Check the current note
Fix active note Insert missing OKF frontmatter
Fix all auto-fixable issues in vault Bulk auto-fix
Migrate note to latest OKF Rewrite timestampgenerated and # Citationssources
Generate/refresh index.md for a folder Build the §8 listing for the active note's folder
Generate/refresh index.md for ALL folders Build listings vault-wide
Add log.md entry (current folder) Append a dated §9 changelog entry

Clicking the status-bar item auto-fixes the active note and, if a required field is still missing, prompts you to fill it.

Settings

Configure under Settings → OKF Enforcer:

  • Default type for auto-fix — value inserted into type when fixing notes that lack it.
  • Default actor for generated.by — the actor recorded when auto-fix adds a generated block (e.g. okf-enforcer/0.6 or human:<id>). It goes into an inline YAML mapping, so it cannot contain a comma.
  • On save — what an edit to the active note triggers: Do nothing, Check the note (validate it and update the status bar), or Check and fix (also insert the missing type, title, and generated). Whichever this is set to, a note is always validated when you open it — that verdict is what the status bar and the report pane's active-note section show.
  • AutomationScan vault on startup and Auto-migrate to latest OKF on fix. The latter is on by default and lets ordinary auto-fix apply the v0.1 → v0.2 migrations; turn it off to keep them behind the explicit command, since a migration rewrites what you wrote.
  • Incomplete index.md — what to do about a folder whose §8 listing is missing or out of date:
    • Ignore — nothing happens on its own; the Generate/refresh index.md commands still write when you run them.
    • Report in the vault scan — a scan warns where a folder has no index.md, and where the one it has doesn't list a note anywhere in the file. Nothing is written. Opening a folder's index.md runs the same check for that one folder, so the active-note section and the status bar agree with the row the scan gives that file. For a vault that keeps its listings by hand: an entry counts under whatever heading and in whatever order its author put it, so only a genuinely absent one is reported. Both findings are warnings — §8 makes an index optional and §11 forbids failing a bundle for a missing one.
    • Write it as notes change (the default) — keep every folder's index.md current as notes are added, renamed, and deleted, along with every listing above it, since a parent describes its subdirectories by what they hold. Every folder gets one — a new or empty folder included, generated as soon as the folder appears and left empty while there is nothing to list.
    • Write it as notes change, and at startup — as above, plus one pass over the whole vault when the plugin loads, for what changed while Obsidian was closed: a vault synced from another machine, or edited outside it. It runs before the startup scan, so the scan judges the listings as they now stand rather than the ones it is about to replace, and it runs quietly — progress shows in the status bar, with no notice at the end.
  • Rebuild existing index.md — off by default, so generating over an existing index adds what's missing, fixes links that point at the wrong path, and removes entries for notes that are gone, changing nothing else. Turn it on to rewrite the listing from the folder's contents instead, which also refreshes every description, re-sorts the entries, and re-groups them under their current type — at the cost of any prose in the file, which a rebuild discards apart from the section named below. It governs the Generate/refresh index.md commands too, so it still matters with Incomplete index.md set to Ignore.
  • Subdirectory description section — heading in a subfolder's index.md whose first paragraph becomes that folder's description in the parent listing (e.g. Purpose). Blank by default, which leaves subdirectory entries undescribed. Additive generation never touches the file's prose, and this is the one section a rebuild carries over, so the description you write survives a refresh either way.
  • RulesWarn about missing fields takes a comma-separated list of the recommended frontmatter fields worth a warning when a note has none: title, description, and generated (the default) are what §4.1 and §5.2 recommend, and tags, which the spec never asks for, is available for a vault that wants it. Leave it blank to warn about none. Validate trust & lifecycle fields and Validate Attested Computation concepts select the remaining optional checks; the former also decides whether the note's trust tier appears in the status-bar tooltip, since the tier is derived from the same §5 verified events the checks read. index.md / log.md structure is always checked: §11 makes it one of the three requirements for a conformant bundle, so it isn't a toggle.
  • Excluded folders — paths skipped during validation and index generation (default: Templates). Use this for attachment folders you'd rather not have an index.md in. The Obsidian config folder (e.g. .obsidian) is always skipped automatically.
  • Batch size — files processed per async chunk (lower = smoother UI on very large vaults).
  • Enable Portent validation (experimental / beta — the Portent spec is pre-1.0 and may change) — layer the Portent spec on top of OKF: default type vocabulary (Project, Operation, Responsibility, Task, Event, Note, Topic, Person), lifecycle metadata (optional and format-free — a single status/state value, boolean organized/archived, or omitted entirely when organized by default), and relationship shape (belongs_to single wikilink, related_to list of wikilinks). All Portent findings are warnings — they never break OKF conformance.
  • Checks — comma-separated: which of Portent's optional checks to run — type, lifecycle, belongs_to, related_to. A note that doesn't carry the field a check looks at is never flagged. Leave blank to run none.
  • Portent schemaType vocabulary and Lifecycle status values set the accepted values, and Field name overrides takes comma-separated concept=key pairs remapping the frontmatter keys Portent reads onto the ones your vault uses (e.g. status=state, belongs_to=parent). Anything you leave out keeps its own name, so a vault that follows the spec leaves the box empty. Between them you can follow your own conventions, or a future spec revision, without waiting for a plugin update.

Installation

Requires Obsidian 1.7.2 or newer.

From the Community Plugins browser

Once accepted: Settings → Community plugins → Browse, search for "OKF Enforcer", install, and enable.

Manual

Download main.js, manifest.json, and styles.css from the latest release into your vault at .obsidian/plugins/okf-enforcer/, then enable the plugin.

Development

npm install
npm run build   # bundles main.ts -> main.js via esbuild

Pushing a version tag (e.g. 0.1.0) triggers the GitHub Actions workflow that builds and attaches main.js, manifest.json, and styles.css to a new release automatically.

Changelog

See CHANGELOG.md.

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md.

License

Apache-2.0.

Acknowledgements

Implements the Open Knowledge Format specification by Google Cloud Platform.

About

Obsidian plugin to validate and enforce the Open Knowledge Format (OKF) with frontmatter checks, auto-fixes, index/log generation, and vault-wide reporting.

Topics

Resources

Contributing

Stars

9 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages