Canon blocks: one source of truth for shared rules in markdown
Canon blocks: sync a shared rule across markdown concepts
Section titled “Canon blocks: sync a shared rule across markdown concepts”Write a rule once in its owner concept. okf copies it into other concepts and tells you when a copy drifts.
The measured version is okf 0.2.5. The runs below use a throwaway copy of the test catalogue.
How it looks
Section titled “How it looks”okf sync-status lists every copy of a canon block and its state. Here the owner text changed after one copy was made:
$ okf --root <catalogue> sync-statussynced handbook/ops/setup.md /kc-gov/ownership.md#ownership-rulesource-changed kc-gov/naming.md /kc-gov/ownership.md#naming-rulesync-status: 1 synced, 1 source-changed, 0 consumer-modified, 0 both-changed, 0 source-missing, 0 malformed[exit 5]Exit 5 means drift was found. After okf sync-update --apply every copy is synced and the exit code is 0:
$ okf --root <catalogue> sync-update --apply--- a/kc-gov/naming.md+++ b/kc-gov/naming.md@@ -9,8 +9,8 @@-<!-- okf:sync id=naming-rule source=/kc-gov/ownership.md hash=68dca574d22c -->+<!-- okf:sync id=naming-rule source=/kc-gov/ownership.md hash=5f1068e89974 --> > [!quote] Synchronisiert aus `/kc-gov/ownership.md` — Canon-Owner, hier nicht bearbeiten. <!-- okf:sync-body -->-Names are lowercase, hyphenated and stable.+Names are lowercase, hyphenated, stable and unique. <!-- /okf:sync -->updated kc-gov/naming.md /kc-gov/ownership.md#naming-rulesync-update: 1 updated, 0 refused, 0 unresolvable.[exit 0]$ okf --root <catalogue> sync-statussynced handbook/ops/setup.md /kc-gov/ownership.md#ownership-rulesynced kc-gov/naming.md /kc-gov/ownership.md#naming-rulesync-status: 2 synced, 0 source-changed, 0 consumer-modified, 0 both-changed, 0 source-missing, 0 malformed[exit 0]Why it matters
Section titled “Why it matters”Edit the canon once and every consumer follows. You do not search for copies of a rule by hand.
What you get
Section titled “What you get”flowchart LR
O["Owner concept<br/>okf:canon id=naming-rule"] -- "sync-insert" --> C1["Consumer A<br/>okf:sync block"]
O -- "sync-insert" --> C2["Consumer B<br/>okf:sync block"]
O -. "edit the owner text" .-> D{"sync-status"}
D -- "source-changed, exit 5" --> U["sync-update --apply"]
U --> C1
U --> C2
okf sync-exportprints the payload of one canon block.okf sync-insertmaterialises a canon block in a consumer concept.okf sync-statusreports the state of every copy.okf sync-updatere-materialises outdated copies from their owner.
okf rename and okf archive of an owner rewrite source= in all its sync blocks (see Safe edits).
Details
Section titled “Details”Marker syntax
Section titled “Marker syntax”The owner concept declares a canon block between two comments:
<!-- okf:canon id=ownership-rule -->Every normative statement has exactly one owner.<!-- /okf:canon -->A consumer concept holds the managed copy, a sync block. It carries the owner path in source= and a 12-hex hash=:
<!-- okf:sync id=ownership-rule source=/kc-gov/ownership.md hash=594970cbf139 -->> [!quote] Synchronisiert aus `/kc-gov/ownership.md` — Canon-Owner, hier nicht bearbeiten.<!-- okf:sync-body -->Every normative statement has exactly one owner.<!-- /okf:sync -->Do not edit the text between okf:sync-body and /okf:sync. The next sync-update replaces it.
Insert and update preview first
Section titled “Insert and update preview first”The argument order of sync-insert is consumer, owner concept, block id. Without --apply okf prints a diff and writes nothing:
$ okf --root <catalogue> sync-insert handbook/glossary kc-gov/ownership naming-rule--- a/handbook/glossary.md+++ b/handbook/glossary.md@@ -14,3 +14,9 @@ ## Concept
One Markdown file with frontmatter.++<!-- okf:sync id=naming-rule source=/kc-gov/ownership.md hash=5f1068e89974 -->+> [!quote] Synchronisiert aus `/kc-gov/ownership.md` — Canon-Owner, hier nicht bearbeiten.+<!-- okf:sync-body -->+Names are lowercase, hyphenated, stable and unique.+<!-- /okf:sync -->would insert handbook/glossary.md /kc-gov/ownership.md#naming-rulesync-insert (dry-run): re-run with --apply.sync-update takes an optional target (<bundle> or <bundle>/<subdir>), --source and --block to narrow the blocks, and --force to discard local edits of a consumer.
Drift states
Section titled “Drift states”sync-status reports one of: synced, source-changed, consumer-modified, both-changed, source-missing, malformed. The okf check rules kc/sync/block, kc/sync/canon-block and kc/sync/stale cover the same blocks (see Conformance checks).
Limits
Section titled “Limits”- The statuses
consumer-modified,both-changed,source-missingandmalformedare listed by okf; this page shows only runs withsyncedandsource-changed. - After an owner
rename --apply, the> [!quote]line of a consumer still names the old path untilsync-updateruns. Observed:source=is rewritten at once, the quote line is not. The status stayssyncedbecause the payload did not change [6peo]. - Only one error path was run:
sync-insertwith a concept argument that does not exist printsnot found: naming-ruleand exits 3.sync-insertwith a block id that does not exist in the owner printsno canon block `nope` in recipes/soup.mdand also exits 3.sync-updateon a path that is not a directory exits 3.
Reference
Section titled “Reference”okf sync-export,okf sync-insertokf sync-status,okf sync-update- Canon block in the glossary