All skills
cwest avatar

/okf-curation-health

@e8fd692
by Casey Westcwest/okfctl8 stars
3

Use when keeping an OKF bundle healthy with okfctl — running validate for spec-floor and type-template conformance, and lint for curation findings (orphans, missing cross-references, broken internal links, coverage gaps, type hygiene), including as a CI or pre-commit gate.

  • 1 file
  • 9.5 KB
  • Apache-2
  • Updated 2 months ago
  • GitHub

Use this Skill: https://skilld.dev/gh/cwest/okfctl/okf-curation-health

This session only. Nothing lands on disk.

SKILL.md

≈74 tokens always: the name and description. ≈2.3k when used: this file.

Keeping an OKF corpus healthy with okfctl

Overview

Two okfctl commands keep a bundle healthy, and they answer different questions:

  • validate — is this a conformant OKF bundle? Spec-floor conformance (hard failures), plus an opt-in type-template overlay for team conventions.
  • lint — is this a well-curated corpus? Judgment-worthy findings (orphans, missing cross-references, broken internal links, coverage gaps, type hygiene). Never a format failure; lint never mutates the bundle.

lint and structural validate require NO model and NO index. They work on a fresh clone with zero setup — pure graph and text analysis. (The one exception, lint --semantic, is covered by okf-semantic-search.)

When to Use

  • You want to know whether a bundle conforms to OKF before publishing/merging.
  • You want curation guidance: what to link, what to write next, what to clean up.
  • You want a nonzero-exit gate for CI or a pre-commit hook.

Don't use for: authoring/scaffolding nodes — see okf-authoring; similarity checks — see okf-semantic-search.

validate — conformance

Spec-floor validation checks that every node carries a non-empty type (OKF §7). Unknown type values are allowed — OKF is anti-taxonomy at the floor.

$ okfctl validate mykb
OK: bundle conforms to the OKF spec floor

A floor violation always fails (exit 1), regardless of any flag:

$ okfctl validate mykb        # a node with an empty `type:`
FAIL concepts/bad.md: missing or empty required field: type
okfctl: 1 conformance finding(s)
$ echo $?
1

Type-template overlay (--templates)

--templates additionally checks each node against its governing type template (if the bundle declares one — see okf-authoring). Template drift (a missing required field or body section) is reported as a warning, advisory by default (exit 0). Add --strict to make drift fail:

$ okfctl validate mykb --templates
warning playbooks/rollback.md: missing required field: owner (template Playbook)
warning playbooks/rollback.md: missing body section: Rollback (template Playbook)
warning playbooks/rollback.md: missing body section: Verification (template Playbook)
3 template drift warning(s)
$ echo $?
0

$ okfctl validate mykb --templates --strict
warning playbooks/rollback.md: missing required field: owner (template Playbook)
...
okfctl: 3 template drift warning(s)
$ echo $?
1

The overlay never leaks into the floor: unknown type values still pass, and spec-floor violations still fail even without --templates.

lint — curation findings

$ okfctl lint mykb
OK: no lint findings          # when clean

With findings, lint prints one line per finding and a count. By default it is advisory and exits 0 even with findings — so it never blocks by accident:

$ okfctl lint mykb
coverage-gap: "Malolactic Fermentation" is referenced by 3 nodes but has no node of its own
type-hygiene: near-duplicate type values likely refer to one type: Concept, Concepts
orphan: concepts/aging.md has no inbound links (unreachable by traversal)
missing-xref: concepts/wine.md mentions "Tannin" but does not link to concepts/tannin.md
9 lint finding(s)
$ echo $?
0

What each finding means and what to do

finding means action
orphan a concept node no node (or index.md) links to — unreachable by traversal link it from a relevant node, or from index.md via index build
missing-xref a node's prose names another node's title as a whole word but doesn't link it add the [Title](path.md) link, or reword if the mention is incidental
broken-link a node links to a .md target that resolves to no node, and a node with that basename exists elsewhere — a moved or mistyped path (a defect, not an unwritten concept) fix the path to the resolved candidate the finding names
coverage-gap a known concept term (declared as a title/alias) is referenced by ≥ threshold distinct nodes but has no node of its own — a node whose title is the term or leads with it counts as its home author the missing node — it's a real to-do, prioritized by mention count
type-hygiene two type values fold to the same canonical form (case / trailing-s plural), e.g. Concept vs Concepts pick one spelling and normalize the drifting nodes

Two accuracy notes that keep you from chasing ghosts:

  • orphan treats index.md as a linker. A node listed in a freshly built index.md is not an orphan. If everything shows as orphaned, run okfctl index build first (see okf-authoring).
  • coverage-gap only fires for known concepts — a term some node declares as a title or aliases: entry. Arbitrary capitalized prose ("Google Cloud", a sentence-initial "The") is deliberately not a candidate; this is what makes the check act on real gaps rather than noise. A concept is considered to have a node when some node's title equals the term or leads with it (e.g. a node titled "Block Buzz vs. Discord…" is the home for "Block Buzz"); an alias on an otherwise-unrelated node marks the term as known but does not, by itself, give it a home. If you expect a gap and don't get one, the term probably already has a home node — or isn't declared as a concept anywhere yet.

broken-link vs a dangling link — defect, not gap

A .md link that resolves to no node is one of two very different things, and lint reports only the dangerous one:

  • The concept doesn't exist yet — a referenced-but-unwritten node. That's a coverage gap: correctly advisory, and it stays out of lint. analyze surfaces it under coverage_gaps.dangling_links where it belongs (a research to-do, not a defect).
  • The concept exists and the path is wrong — a typo, a moved file, a bad find-and-replace. That's a defect, and it's dangerous because it's silent: everything still validates, nothing is orphaned, yet a link points nowhere. broken-link is the gate for exactly this case.

The discriminator is basename: lint reports a dangling target as broken-link only when a node with the same basename lives elsewhere in the bundle — the signature of a moved or mistyped path. This is the check to lean on before a bulk migration (node mv, a directory reorg, a wikilink→Markdown rewrite): those operations produce exactly the defect signature, and lint --strict will catch them in CI. analyze's advisory dangling-link reporting is unchanged — this check only adds a gate.

Tuning the coverage-gap threshold

Default threshold is 3 distinct nodes. Lower it to surface gaps earlier, raise it to only flag heavily-referenced missing concepts:

$ okfctl lint mykb --coverage-threshold 2

Gate CI / pre-commit with --strict

lint is advisory by default; --strict makes any finding exit non-zero so it can gate a pipeline:

$ okfctl lint mykb --strict
orphan: concepts/mouthfeel.md has no inbound links (unreachable by traversal)
1 lint finding(s)
okfctl: 1 lint finding(s)
$ echo $?
1

A pre-commit hook, for example:

- repo: local
  hooks:
    - id: okf-lint
      name: OKF curation lint
      entry: okfctl lint . --strict
      language: system
      pass_filenames: false

Because structural lint needs no model and no index, this gate runs on a fresh clone with nothing installed but the okfctl binary. For a CI conformance gate, pair it with okfctl validate . --templates --strict and okfctl index check ..

Common Pitfalls

  1. Everything shows as orphan. You haven't run okfctl index build. index.md confers reachability; without a current index, nodes linked only from the (stale/empty) table of contents read as orphaned.

  2. Expecting coverage-gap on any repeated word. It only reports known concept terms (declared as a title or aliases:). Lowercase prose and undeclared proper nouns are intentionally excluded — the check targets real authoring to-dos, not vocabulary frequency.

  3. Assuming lint blocks CI by default. It exits 0 even with findings unless you pass --strict. A pipeline that forgot --strict will go green on a corpus full of findings.

  4. Using lint to catch format errors. lint is curation guidance, never conformance. Spec-floor violations (missing/empty type) surface only in validate, which fails on them regardless of flags.

  5. Confusing --templates warnings with floor failures. Template drift is advisory (exit 0) unless --strict; a genuine spec-floor violation fails unconditionally. They are separate exit paths.

Verification Checklist

  • okfctl validate <dir> exits 0 (spec floor clean)
  • If the bundle declares type templates, okfctl validate <dir> --templates reviewed; --strict used where drift must block
  • okfctl lint <dir> reviewed; each finding class understood and actioned
  • okfctl index build run before trusting orphan findings
  • CI/pre-commit gate uses --strict so findings actually block

Source: SKILL.md on GitHub

No third-party reports yet.

Signed by skilld at e8fd692. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 2 months ago
version
1.0.0
author
okfctl
Other metadata
metadata
{
  "hermes": {
    "tags": [
      "okfctl",
      "okf",
      "lint",
      "validate",
      "curation",
      "ci",
      "knowledge-graph"
    ],
    "related_skills": [
      "okf-authoring",
      "okf-semantic-search"
    ],
    "sharing": "shareable"
  }
}

README badge

README badge for cwest/okfctl/okf-curation-health