okf 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.okf/capabilities/agent-skill.md +46 -0
- data/.okf/capabilities/graph-server.md +60 -0
- data/.okf/capabilities/index.md +20 -0
- data/.okf/capabilities/library-api.md +67 -0
- data/.okf/capabilities/linter.md +49 -0
- data/.okf/capabilities/read-views.md +84 -0
- data/.okf/capabilities/validator.md +40 -0
- data/.okf/cli.md +52 -0
- data/.okf/design/core-shell-split.md +58 -0
- data/.okf/design/index.md +10 -0
- data/.okf/design/ruby-floor.md +45 -0
- data/.okf/design/runtime-dependencies.md +44 -0
- data/.okf/design/server-trust-boundary.md +35 -0
- data/.okf/format/citations.md +33 -0
- data/.okf/format/cross-links.md +52 -0
- data/.okf/format/frontmatter.md +38 -0
- data/.okf/format/index.md +9 -0
- data/.okf/format/okf-format.md +43 -0
- data/.okf/index.md +18 -0
- data/.okf/log.md +9 -0
- data/.okf/model/bundle.md +38 -0
- data/.okf/model/concept.md +44 -0
- data/.okf/model/graph.md +44 -0
- data/.okf/model/index.md +8 -0
- data/.okf/overview.md +66 -0
- data/CHANGELOG.md +54 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +201 -0
- data/NOTICE +10 -0
- data/README.md +276 -0
- data/exe/okf +6 -0
- data/lib/okf/bundle/folder.rb +94 -0
- data/lib/okf/bundle/graph.rb +118 -0
- data/lib/okf/bundle/linter/report.rb +56 -0
- data/lib/okf/bundle/linter.rb +416 -0
- data/lib/okf/bundle/reader.rb +60 -0
- data/lib/okf/bundle/validator/result.rb +35 -0
- data/lib/okf/bundle/validator.rb +131 -0
- data/lib/okf/bundle/writer.rb +137 -0
- data/lib/okf/bundle.rb +216 -0
- data/lib/okf/cli.rb +910 -0
- data/lib/okf/concept/file.rb +63 -0
- data/lib/okf/concept.rb +101 -0
- data/lib/okf/markdown/citations.rb +49 -0
- data/lib/okf/markdown/frontmatter.rb +55 -0
- data/lib/okf/markdown/links.rb +98 -0
- data/lib/okf/path.rb +34 -0
- data/lib/okf/server/app.rb +120 -0
- data/lib/okf/server/graph.rb +112 -0
- data/lib/okf/server/runner.rb +78 -0
- data/lib/okf/server/templates/graph.html.erb +803 -0
- data/lib/okf/skill/SKILL.md +133 -0
- data/lib/okf/skill/reference/APACHE-2.0.txt +202 -0
- data/lib/okf/skill/reference/SPEC.md +460 -0
- data/lib/okf/skill/reference/authoring.md +218 -0
- data/lib/okf/skill/reference/cli.md +196 -0
- data/lib/okf/skill/templates/concept.md +24 -0
- data/lib/okf/skill/templates/index.md +8 -0
- data/lib/okf/skill/templates/log.md +6 -0
- data/lib/okf/skill/templates/root-index.md +12 -0
- data/lib/okf/skill.rb +82 -0
- data/lib/okf/version.rb +5 -0
- data/lib/okf.rb +55 -0
- metadata +142 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Vendored from the Open Knowledge Format reference repository.
|
|
3
|
+
Source: https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md
|
|
4
|
+
Commit: ee67a5ca27044ebe7c38385f5b6cffc2305a9c1a
|
|
5
|
+
License: Apache-2.0 (c) Google LLC — included verbatim under its terms.
|
|
6
|
+
Full license text: ./APACHE-2.0.txt
|
|
7
|
+
This is the canonical normative reference loaded by the okf skill.
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
# Open Knowledge Format (OKF)
|
|
11
|
+
|
|
12
|
+
**Version 0.1 — Draft**
|
|
13
|
+
|
|
14
|
+
OKF is an open, human- and agent-friendly format for representing
|
|
15
|
+
*knowledge* — the metadata, context, and curated insight that surrounds
|
|
16
|
+
data and systems. It is designed to be authored by people, generated by
|
|
17
|
+
agents, exchanged across organizations, and consumed by both.
|
|
18
|
+
|
|
19
|
+
The format is intentionally minimal: a directory of markdown files with
|
|
20
|
+
YAML frontmatter. There is no schema registry, no central authority, and
|
|
21
|
+
no required tooling. If you can `cat` a file, you can read OKF; if you
|
|
22
|
+
can `git clone` a repo, you can ship it.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 1. Motivation
|
|
27
|
+
|
|
28
|
+
The space of knowledge representation for AI agents is evolving quickly,
|
|
29
|
+
and many incompatible conventions are emerging. OKF takes the position
|
|
30
|
+
that knowledge is best represented in commonly accessible, established
|
|
31
|
+
formats that are:
|
|
32
|
+
|
|
33
|
+
- **Readable** by humans without tooling.
|
|
34
|
+
- **Parseable** by agents without bespoke SDKs.
|
|
35
|
+
- **Diffable** in version control.
|
|
36
|
+
- **Portable** across tools, organizations, and time.
|
|
37
|
+
|
|
38
|
+
The format is minimally opinionated. It standardizes only the small set
|
|
39
|
+
of structural conventions needed to make a knowledge corpus
|
|
40
|
+
*self-describing* — anything beyond that is left to the producer.
|
|
41
|
+
|
|
42
|
+
### Goals
|
|
43
|
+
|
|
44
|
+
1. Define a universal format that **enrichment agents** can write into.
|
|
45
|
+
2. Inform how **consumption agents** should read and traverse it.
|
|
46
|
+
3. Facilitate **exchange** of knowledge across systems and organizations.
|
|
47
|
+
4. Standardize the small number of **required** fields that must be
|
|
48
|
+
present for content to be meaningfully consumed.
|
|
49
|
+
|
|
50
|
+
### Non-goals
|
|
51
|
+
|
|
52
|
+
- Defining a fixed taxonomy of concept types.
|
|
53
|
+
- Prescribing storage, serving, or query infrastructure.
|
|
54
|
+
- Replacing domain-specific schemas (Avro, Protobuf, OpenAPI, etc.) —
|
|
55
|
+
OKF *references* them; it does not subsume them.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 2. Terminology
|
|
60
|
+
|
|
61
|
+
- **Knowledge Bundle** — A self-contained, hierarchical collection of
|
|
62
|
+
knowledge documents. The unit of distribution.
|
|
63
|
+
- **Concept** — A single unit of knowledge within a bundle. Represented
|
|
64
|
+
as one markdown document. May describe a tangible asset (a table, an
|
|
65
|
+
API), an abstract idea (a metric, a business process), or anything in
|
|
66
|
+
between.
|
|
67
|
+
- **Concept ID** — The path of the concept's file within the bundle,
|
|
68
|
+
with the `.md` suffix removed. For example, `tables/users.md` has
|
|
69
|
+
concept ID `tables/users`.
|
|
70
|
+
- **Frontmatter** — YAML metadata block delimited by `---` at the top of
|
|
71
|
+
a markdown file.
|
|
72
|
+
- **Body** — Everything in the file after the frontmatter.
|
|
73
|
+
- **Link** — A standard markdown link from one concept to another, used
|
|
74
|
+
to express relationships beyond the implicit parent/child hierarchy.
|
|
75
|
+
- **Citation** — A link from a concept to an external source that
|
|
76
|
+
supports a claim in the body.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 3. Bundle Structure
|
|
81
|
+
|
|
82
|
+
A bundle is a directory tree of markdown files. The directory structure
|
|
83
|
+
is independent of the domain — producers organize concepts however makes
|
|
84
|
+
sense for the knowledge being captured.
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
path/to/bundle/
|
|
88
|
+
├── index.md # Optional. Directory listing for progressive disclosure.
|
|
89
|
+
├── log.md # Optional. Chronological history of updates.
|
|
90
|
+
├── <concept>.md # A concept at the bundle root.
|
|
91
|
+
└── <subdirectory>/ # Subdirectories organize concepts into groups.
|
|
92
|
+
├── index.md
|
|
93
|
+
├── <concept>.md
|
|
94
|
+
└── <subdirectory>/
|
|
95
|
+
└── …
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
A bundle MAY be distributed as:
|
|
99
|
+
|
|
100
|
+
- A git repository (recommended — provides history, attribution, diffs).
|
|
101
|
+
- A tarball or zip archive of the directory.
|
|
102
|
+
- A subdirectory within a larger repository.
|
|
103
|
+
|
|
104
|
+
### 3.1 Reserved filenames
|
|
105
|
+
|
|
106
|
+
The following filenames have defined meaning at any level of the
|
|
107
|
+
hierarchy and MUST NOT be used for concept documents:
|
|
108
|
+
|
|
109
|
+
| Filename | Purpose |
|
|
110
|
+
|--------------|--------------------------------------------------------|
|
|
111
|
+
| `index.md` | Directory listing. See §6. |
|
|
112
|
+
| `log.md` | Update history. See §7. |
|
|
113
|
+
|
|
114
|
+
All other `.md` files are concept documents.
|
|
115
|
+
|
|
116
|
+
Tags themselves remain a first-class concept — see the `tags`
|
|
117
|
+
frontmatter field in §4.1. OKF does not specify a separate file format
|
|
118
|
+
for aggregating documents by tag; producers that want a tag-browsing
|
|
119
|
+
view can synthesize one at consumption time by scanning frontmatter.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 4. Concept Documents
|
|
124
|
+
|
|
125
|
+
Every concept is a UTF-8 markdown file. It has two parts:
|
|
126
|
+
|
|
127
|
+
1. A **YAML frontmatter block**, delimited by `---` on its own line at
|
|
128
|
+
the start of the file and a closing `---` on its own line.
|
|
129
|
+
2. A **markdown body**, containing free-form content.
|
|
130
|
+
|
|
131
|
+
### 4.1 Frontmatter
|
|
132
|
+
|
|
133
|
+
```yaml
|
|
134
|
+
---
|
|
135
|
+
type: <Type name> # REQUIRED
|
|
136
|
+
title: <Optional display name>
|
|
137
|
+
description: <Optional one-line summary>
|
|
138
|
+
resource: <Optional canonical URI for the underlying asset>
|
|
139
|
+
tags: [<tag>, <tag>, …] # Optional
|
|
140
|
+
timestamp: <ISO 8601 datetime> # Optional last-modified time
|
|
141
|
+
# … other producer-defined key/value pairs
|
|
142
|
+
---
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Required:**
|
|
146
|
+
|
|
147
|
+
- `type` — A short string identifying the kind of concept. Consumers
|
|
148
|
+
use this for routing, filtering, and presentation. Example values:
|
|
149
|
+
`BigQuery Table`, `BigQuery Dataset`, `API Endpoint`, `Metric`,
|
|
150
|
+
`Playbook`, `Reference`.
|
|
151
|
+
|
|
152
|
+
Type values are **not** registered centrally. Producers SHOULD pick
|
|
153
|
+
values that are descriptive and self-explanatory; consumers MUST
|
|
154
|
+
tolerate unknown types gracefully (typically by treating them as
|
|
155
|
+
generic concepts).
|
|
156
|
+
|
|
157
|
+
**Recommended (in priority order):**
|
|
158
|
+
|
|
159
|
+
- `title` — Human-readable display name. If omitted, consumers MAY
|
|
160
|
+
derive a title from the filename.
|
|
161
|
+
- `description` — A single sentence summarizing the concept. Used by
|
|
162
|
+
`index.md` generators, search snippets, and previews.
|
|
163
|
+
- `resource` — A URI that uniquely identifies the underlying asset the
|
|
164
|
+
concept describes. Absent for concepts that describe abstract ideas
|
|
165
|
+
rather than physical resources.
|
|
166
|
+
- `tags` — A YAML list of short strings for cross-cutting categorization.
|
|
167
|
+
- `timestamp` — ISO 8601 datetime of last meaningful change.
|
|
168
|
+
|
|
169
|
+
**Extensions:** Producers MAY include any additional keys. Consumers
|
|
170
|
+
SHOULD preserve unknown keys when round-tripping and SHOULD NOT reject
|
|
171
|
+
documents with unrecognized fields.
|
|
172
|
+
|
|
173
|
+
### 4.2 Body
|
|
174
|
+
|
|
175
|
+
The body is standard markdown. Producers SHOULD favor structural
|
|
176
|
+
markdown — headings, lists, tables, fenced code blocks — over freeform
|
|
177
|
+
prose, since structure aids both human reading and agent retrieval.
|
|
178
|
+
|
|
179
|
+
There are no required body sections. The following section headings have
|
|
180
|
+
**conventional** meaning and SHOULD be used when applicable:
|
|
181
|
+
|
|
182
|
+
| Heading | Purpose |
|
|
183
|
+
|----------------|--------------------------------------------------------|
|
|
184
|
+
| `# Schema` | Structured description of an asset's columns/fields. |
|
|
185
|
+
| `# Examples` | Concrete usage examples, often as fenced code blocks. |
|
|
186
|
+
| `# Citations` | External sources backing claims in the body. See §8. |
|
|
187
|
+
|
|
188
|
+
### 4.3 Example: a concept bound to a resource
|
|
189
|
+
|
|
190
|
+
```markdown
|
|
191
|
+
---
|
|
192
|
+
type: BigQuery Table
|
|
193
|
+
title: Customer Orders
|
|
194
|
+
description: One row per completed customer order across all channels.
|
|
195
|
+
resource: https://console.cloud.google.com/bigquery?p=acme&d=sales&t=orders
|
|
196
|
+
tags: [sales, orders, revenue]
|
|
197
|
+
timestamp: 2026-05-28T14:30:00Z
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
# Schema
|
|
201
|
+
|
|
202
|
+
| Column | Type | Description |
|
|
203
|
+
|---------------|-----------|------------------------------------------|
|
|
204
|
+
| `order_id` | STRING | Globally unique order identifier. |
|
|
205
|
+
| `customer_id` | STRING | Foreign key into [customers](/tables/customers.md). |
|
|
206
|
+
| `total_usd` | NUMERIC | Order total in US dollars. |
|
|
207
|
+
| `placed_at` | TIMESTAMP | When the customer submitted the order. |
|
|
208
|
+
|
|
209
|
+
# Joins
|
|
210
|
+
|
|
211
|
+
Joined with [customers](/tables/customers.md) on `customer_id`.
|
|
212
|
+
|
|
213
|
+
# Citations
|
|
214
|
+
|
|
215
|
+
[1] [BigQuery table schema](https://console.cloud.google.com/bigquery?p=acme&d=sales&t=orders)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 4.4 Example: a concept not bound to a resource
|
|
219
|
+
|
|
220
|
+
```markdown
|
|
221
|
+
---
|
|
222
|
+
type: Playbook
|
|
223
|
+
title: Incident response — data freshness alert
|
|
224
|
+
description: Steps to triage a freshness alert on the orders pipeline.
|
|
225
|
+
tags: [oncall, incident]
|
|
226
|
+
timestamp: 2026-04-12T09:00:00Z
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
# Trigger
|
|
230
|
+
|
|
231
|
+
A freshness alert fires when `orders` lags more than 30 minutes behind
|
|
232
|
+
its expected SLA. See the [orders table](/tables/orders.md).
|
|
233
|
+
|
|
234
|
+
# Steps
|
|
235
|
+
|
|
236
|
+
1. Check the [ingestion job dashboard](https://example.com/dash).
|
|
237
|
+
2. …
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 5. Cross-linking
|
|
243
|
+
|
|
244
|
+
Concepts MAY link to other concepts using standard markdown links. Two
|
|
245
|
+
forms are supported:
|
|
246
|
+
|
|
247
|
+
### 5.1 Absolute (bundle-relative) links
|
|
248
|
+
|
|
249
|
+
Begin with `/`, interpreted relative to the bundle root.
|
|
250
|
+
|
|
251
|
+
```markdown
|
|
252
|
+
See the [customers table](/tables/customers.md) for the join key.
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
This is the **recommended** form because it is stable when documents are
|
|
256
|
+
moved within their subdirectory.
|
|
257
|
+
|
|
258
|
+
### 5.2 Relative links
|
|
259
|
+
|
|
260
|
+
Standard markdown relative paths.
|
|
261
|
+
|
|
262
|
+
```markdown
|
|
263
|
+
See the [neighboring concept](./other.md).
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 5.3 Link semantics
|
|
267
|
+
|
|
268
|
+
A link from concept A to concept B asserts a *relationship*. The
|
|
269
|
+
specific kind of relationship (parent/child, references, joins-with,
|
|
270
|
+
depends-on, etc.) is conveyed by the surrounding prose, not by the link
|
|
271
|
+
itself. Consumers that build a graph view typically treat all links as
|
|
272
|
+
directed edges of an untyped relationship.
|
|
273
|
+
|
|
274
|
+
Consumers MUST tolerate broken links — a link whose target does not
|
|
275
|
+
exist in the bundle is not malformed; it may simply represent
|
|
276
|
+
not-yet-written knowledge.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## 6. Index Files
|
|
281
|
+
|
|
282
|
+
An `index.md` file MAY appear in any directory, including the bundle
|
|
283
|
+
root. It enumerates the directory's contents to support **progressive
|
|
284
|
+
disclosure** — letting a human or agent see what is available before
|
|
285
|
+
opening individual documents.
|
|
286
|
+
|
|
287
|
+
Index files contain no frontmatter. The body uses one or more sections,
|
|
288
|
+
each grouping concepts under a heading:
|
|
289
|
+
|
|
290
|
+
```markdown
|
|
291
|
+
# Section / Group Heading
|
|
292
|
+
|
|
293
|
+
* [Title 1](relative-url-1) - short description of item 1
|
|
294
|
+
* [Title 2](relative-url-2) - short description of item 2
|
|
295
|
+
|
|
296
|
+
# Another Section
|
|
297
|
+
|
|
298
|
+
* [Subdirectory](subdir/) - short description of the subdirectory
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Entries SHOULD include the description from the linked concept's
|
|
302
|
+
frontmatter. Producers MAY generate `index.md` automatically; consumers
|
|
303
|
+
MAY synthesize one on the fly when none is present.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## 7. Log Files (optional)
|
|
308
|
+
|
|
309
|
+
A `log.md` file MAY appear at any level of the hierarchy to record the
|
|
310
|
+
history of changes to that scope. The format is a flat list of
|
|
311
|
+
date-grouped entries, newest first:
|
|
312
|
+
|
|
313
|
+
```markdown
|
|
314
|
+
# Directory Update Log
|
|
315
|
+
|
|
316
|
+
## 2026-05-22
|
|
317
|
+
* **Update**: Added new BigQuery table reference for [Customer Metrics](/tables/customer-metrics.md).
|
|
318
|
+
* **Creation**: Established the [Dataplex Playbook](/playbooks/dataplex.md).
|
|
319
|
+
|
|
320
|
+
## 2026-05-15
|
|
321
|
+
* **Initialization**: Created foundational directory structure.
|
|
322
|
+
* **Update**: Added progressive-disclosure guidelines to the root [index](/index.md).
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Date headings MUST use ISO 8601 `YYYY-MM-DD` form. Log entries are
|
|
326
|
+
prose; the leading bold word (`**Update**`, `**Creation**`,
|
|
327
|
+
`**Deprecation**`, etc.) is a convention, not a requirement.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## 8. Citations
|
|
332
|
+
|
|
333
|
+
When a concept's body makes claims sourced from external material,
|
|
334
|
+
those sources SHOULD be listed under a `# Citations` heading at the
|
|
335
|
+
bottom of the document, numbered:
|
|
336
|
+
|
|
337
|
+
```markdown
|
|
338
|
+
# Citations
|
|
339
|
+
|
|
340
|
+
[1] [BigQuery public dataset announcement](https://cloud.google.com/blog/products/data-analytics/...)
|
|
341
|
+
[2] [Internal data quality runbook](https://wiki.acme.internal/data/quality)
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Citation links MAY be absolute URLs, bundle-relative paths, or paths
|
|
345
|
+
into a `references/` subdirectory that mirrors external material as
|
|
346
|
+
first-class OKF concepts.
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## 9. Conformance
|
|
351
|
+
|
|
352
|
+
A bundle is **conformant** with OKF v0.1 if:
|
|
353
|
+
|
|
354
|
+
1. Every non-reserved `.md` file in the tree contains a parseable YAML
|
|
355
|
+
frontmatter block.
|
|
356
|
+
2. Every frontmatter block contains a non-empty `type` field.
|
|
357
|
+
3. Every reserved filename (`index.md`, `log.md`) follows the structure
|
|
358
|
+
described in §6 and §7 respectively when present.
|
|
359
|
+
|
|
360
|
+
Consumers SHOULD treat all other constraints as soft guidance. In
|
|
361
|
+
particular, consumers MUST NOT reject a bundle because of:
|
|
362
|
+
|
|
363
|
+
- Missing optional frontmatter fields.
|
|
364
|
+
- Unknown `type` values.
|
|
365
|
+
- Unknown additional frontmatter keys.
|
|
366
|
+
- Broken cross-links.
|
|
367
|
+
- Missing `index.md` files.
|
|
368
|
+
|
|
369
|
+
This permissive consumption model is intentional: OKF is meant to
|
|
370
|
+
remain useful as bundles grow, get refactored, and are partially
|
|
371
|
+
generated by agents.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## 10. Relationship to other formats
|
|
376
|
+
|
|
377
|
+
OKF is intentionally close to several established patterns:
|
|
378
|
+
|
|
379
|
+
- **LLM "wiki" repositories** that use markdown + frontmatter as
|
|
380
|
+
agent-readable knowledge bases.
|
|
381
|
+
- **Personal knowledge tools** like Obsidian and Notion, which use
|
|
382
|
+
hierarchical markdown with cross-links.
|
|
383
|
+
- **"Metadata as code"** approaches that store catalog metadata
|
|
384
|
+
alongside source code rather than in a separate registry.
|
|
385
|
+
|
|
386
|
+
OKF differs primarily in being **specified** — pinning down the small
|
|
387
|
+
set of rules needed for interoperability without dictating tooling.
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## 11. Versioning
|
|
392
|
+
|
|
393
|
+
This document specifies OKF version **0.1**. Future revisions will be
|
|
394
|
+
versioned in the form `<major>.<minor>`:
|
|
395
|
+
|
|
396
|
+
- A **minor** version bump introduces backward-compatible additions
|
|
397
|
+
(new optional fields, new conventional section headings).
|
|
398
|
+
- A **major** version bump may make breaking changes (renaming required
|
|
399
|
+
fields, changing reserved filenames).
|
|
400
|
+
|
|
401
|
+
Bundles MAY declare the OKF version they target by including
|
|
402
|
+
`okf_version: "0.1"` in a bundle-root `index.md` frontmatter block (the
|
|
403
|
+
only place frontmatter is permitted in an `index.md`). Consumers that
|
|
404
|
+
do not understand the declared version SHOULD attempt best-effort
|
|
405
|
+
consumption rather than refusing the bundle.
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Appendix A — Minimal example bundle
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
my_bundle/
|
|
413
|
+
├── index.md
|
|
414
|
+
├── datasets/
|
|
415
|
+
│ ├── index.md
|
|
416
|
+
│ └── sales.md
|
|
417
|
+
└── tables/
|
|
418
|
+
├── index.md
|
|
419
|
+
├── orders.md
|
|
420
|
+
└── customers.md
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
`datasets/sales.md`:
|
|
424
|
+
|
|
425
|
+
```markdown
|
|
426
|
+
---
|
|
427
|
+
type: BigQuery Dataset
|
|
428
|
+
title: Sales
|
|
429
|
+
description: All sales-related tables for the retail business.
|
|
430
|
+
resource: https://console.cloud.google.com/bigquery?p=acme&d=sales
|
|
431
|
+
tags: [sales]
|
|
432
|
+
timestamp: 2026-05-28T00:00:00Z
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
The sales dataset contains transactional tables, including
|
|
436
|
+
[orders](/tables/orders.md) and [customers](/tables/customers.md).
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
`tables/orders.md`:
|
|
440
|
+
|
|
441
|
+
```markdown
|
|
442
|
+
---
|
|
443
|
+
type: BigQuery Table
|
|
444
|
+
title: Orders
|
|
445
|
+
description: One row per completed customer order.
|
|
446
|
+
resource: https://console.cloud.google.com/bigquery?p=acme&d=sales&t=orders
|
|
447
|
+
tags: [sales, orders]
|
|
448
|
+
timestamp: 2026-05-28T00:00:00Z
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
# Schema
|
|
452
|
+
|
|
453
|
+
| Column | Type | Description |
|
|
454
|
+
|---------------|-----------|------------------------------|
|
|
455
|
+
| `order_id` | STRING | Unique order identifier. |
|
|
456
|
+
| `customer_id` | STRING | FK to [customers](/tables/customers.md). |
|
|
457
|
+
| `total_usd` | NUMERIC | Order total in USD. |
|
|
458
|
+
|
|
459
|
+
Part of the [sales dataset](/datasets/sales.md).
|
|
460
|
+
```
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Authoring OKF well — the craft
|
|
2
|
+
|
|
3
|
+
The spec ([SPEC.md](SPEC.md)) tells you what is *legal*. This file is what is
|
|
4
|
+
*good* — the modelling judgment that turns a pile of conformant files into
|
|
5
|
+
knowledge worth consuming. Read it before `produce` or `maintain`, and keep the §9
|
|
6
|
+
conformance rules in mind (parseable frontmatter, a non-empty `type`, and
|
|
7
|
+
well-formed reserved files — the hard rules in [SKILL.md](../SKILL.md)); everything
|
|
8
|
+
else is guidance a consumer must tolerate.
|
|
9
|
+
|
|
10
|
+
## What each SPEC section governs
|
|
11
|
+
|
|
12
|
+
Consult the right section on demand instead of re-reading all of [SPEC.md](SPEC.md):
|
|
13
|
+
|
|
14
|
+
| § | Governs | Reach for it when |
|
|
15
|
+
|---|---------|-------------------|
|
|
16
|
+
| §3 | bundle structure, reserved filenames | laying out directories |
|
|
17
|
+
| §4 | concept documents & frontmatter | writing or validating a concept |
|
|
18
|
+
| §5 / §5.3 | cross-links; **broken links are tolerated** | linking; judging a "broken" link |
|
|
19
|
+
| §6 | index files & progressive disclosure | orienting; writing or synthesizing an index |
|
|
20
|
+
| §7 | log files | recording history |
|
|
21
|
+
| §8 | citations & provenance | any external or empirical claim |
|
|
22
|
+
| §9 | conformance — the hard gate | what `validate` may and may not reject |
|
|
23
|
+
| §11 | versioning (`okf_version`) | the root index's one allowed field |
|
|
24
|
+
|
|
25
|
+
## Modelling principles
|
|
26
|
+
|
|
27
|
+
These are the decisions that make or break a bundle. None are enforced by the
|
|
28
|
+
tools — they are yours to get right.
|
|
29
|
+
|
|
30
|
+
### One concept = one file — but what is a concept?
|
|
31
|
+
A concept is the smallest unit of knowledge someone would want to **link to or
|
|
32
|
+
cite on its own**. If two things are always referenced together, they are one
|
|
33
|
+
concept; if either is referenced alone, split them. Err atomic — it is cheap to
|
|
34
|
+
link two files and expensive to untangle one that grew two identities. Signs a
|
|
35
|
+
file should split: two `type`s fighting for the frontmatter, two audiences, or a
|
|
36
|
+
heading that others would plausibly link to directly. The file path (minus `.md`)
|
|
37
|
+
is the concept's stable ID, so name it for what it *is*, not where it sits today.
|
|
38
|
+
|
|
39
|
+
### `type` is the graph's vocabulary
|
|
40
|
+
`type` is the only required field, and it is the dimension every consumer groups
|
|
41
|
+
and colours by (the graph server colours nodes by it; graph analysis clusters by
|
|
42
|
+
it). It is freeform — the spec does not enumerate types — and that freedom is a
|
|
43
|
+
responsibility. Keep a **small, consistent, descriptive** vocabulary per bundle
|
|
44
|
+
(`Service`, `Dataset`, `Metric`, `Decision`, `Playbook`, `Runbook`, …). Reusing
|
|
45
|
+
types across files is what makes the graph legible; inventing a new type per file
|
|
46
|
+
makes `type` meaningless. Before adding a new type, check what the bundle already
|
|
47
|
+
uses.
|
|
48
|
+
|
|
49
|
+
### Tags are the connective axis — curate them like a vocabulary
|
|
50
|
+
`type` says what a concept *is*; the directory says where it *lives*; `tags` are
|
|
51
|
+
the only axis that cuts across both. A tag earns its place one of two ways: by
|
|
52
|
+
**connecting** concepts that type and area don't already group (a `billing` tag
|
|
53
|
+
spanning a service, a dataset, and a decision), or by **marking** something worth
|
|
54
|
+
flagging even on one concept (`security`, `deprecated`). A tag that merely
|
|
55
|
+
restates the concept's own type, area, or title adds no edge — it is noise wearing
|
|
56
|
+
a tag's clothes. Reuse before minting: run `okf tags <dir>` and pick from the
|
|
57
|
+
existing vocabulary first; 2–4 tags per concept is plenty. Scattered singletons
|
|
58
|
+
are how a vocabulary rots into one label per file.
|
|
59
|
+
|
|
60
|
+
### Topology: organize by domain, not by type
|
|
61
|
+
Lay out directories by what the knowledge is *about* (`services/`, `datasets/`,
|
|
62
|
+
`decisions/`), not by concept type. The directory tree is itself knowledge — it
|
|
63
|
+
shows a reader how the system decomposes, and it usually mirrors the shape of the
|
|
64
|
+
codebase or the org. A `types/`-first layout scatters related concepts and buries
|
|
65
|
+
the domain.
|
|
66
|
+
|
|
67
|
+
### `resource` is the bridge to reality
|
|
68
|
+
Set `resource` (a canonical URI) **only** when a concept *is* a real, addressable
|
|
69
|
+
asset — a table (`bigquery://…`), a service repo, a dashboard, an endpoint. Its
|
|
70
|
+
presence is what lets `maintain` find every concept affected by a changed asset by
|
|
71
|
+
grepping for that URI. Abstract concepts — a decision, a principle, a metric
|
|
72
|
+
definition — have no resource, and **omitting it is meaningful**, not laziness. Do
|
|
73
|
+
not invent placeholder URIs.
|
|
74
|
+
|
|
75
|
+
### Links are untyped on purpose
|
|
76
|
+
A markdown link asserts only "these two relate." The *kind* of relationship —
|
|
77
|
+
depends-on, supersedes, derived-from, owns — lives in the **prose around the
|
|
78
|
+
link**, never in a made-up typed-edge syntax. Write the sentence that explains the
|
|
79
|
+
relationship and put the link inside it. Prefer absolute bundle-relative targets
|
|
80
|
+
(`/services/auth-api.md`) so links survive file moves. A link to a concept that
|
|
81
|
+
does not exist yet is fine — it is not-yet-written knowledge (§5.3), and `lint`'s
|
|
82
|
+
backlog will surface it as demand.
|
|
83
|
+
|
|
84
|
+
### Provenance is what makes knowledge trustworthy (§8)
|
|
85
|
+
Any external or empirical claim — a latency number, an approval, a quota, a
|
|
86
|
+
"because X team decided Y" — should carry a citation to its source under a
|
|
87
|
+
`# Citations` heading. Uncited claims are exactly how a bundle decays into folklore
|
|
88
|
+
nobody trusts. `lint`'s provenance category exists to catch missing and broken
|
|
89
|
+
citations; write them as you go so you never have to reconstruct them.
|
|
90
|
+
|
|
91
|
+
### Capture the non-obvious — not what code already says
|
|
92
|
+
A bundle that restates function signatures or config keys goes stale the moment
|
|
93
|
+
the code changes and adds no knowledge. Capture what you **cannot** derive by
|
|
94
|
+
reading one source file: the *why* behind a design, cross-cutting relationships,
|
|
95
|
+
decisions and their tradeoffs, operational tribal knowledge, the metric that
|
|
96
|
+
actually matters. If the code or git history already records it faithfully, link
|
|
97
|
+
to it rather than duplicating it.
|
|
98
|
+
|
|
99
|
+
### Write for both readers at once
|
|
100
|
+
Use structural markdown so an agent can extract deterministically and a human can
|
|
101
|
+
skim: headings, tables, fenced code, lists. Conventional headings a reader expects
|
|
102
|
+
are `# Schema` (field/column tables), `# Examples`, and `# Citations`. Fill
|
|
103
|
+
recommended frontmatter — `title`, `description`, `tags`, `timestamp` (ISO 8601) —
|
|
104
|
+
whenever it aids consumption.
|
|
105
|
+
|
|
106
|
+
### Reserved files
|
|
107
|
+
`index.md` is a directory listing and carries **no frontmatter** — with one
|
|
108
|
+
exception: the **bundle-root** `index.md` is the only index that may carry
|
|
109
|
+
frontmatter, and it may carry *only* `okf_version: "0.1"` (§11; `validate` §9.3
|
|
110
|
+
flags any other key there). `log.md` is an ISO-dated change history, newest first.
|
|
111
|
+
Never use these names for concepts. Templates:
|
|
112
|
+
[concept](../templates/concept.md), nested [index](../templates/index.md),
|
|
113
|
+
bundle-root [root-index](../templates/root-index.md), [log](../templates/log.md).
|
|
114
|
+
|
|
115
|
+
## Playbooks
|
|
116
|
+
|
|
117
|
+
### produce — create or extend a bundle
|
|
118
|
+
1. Read [SPEC.md](SPEC.md) if you are unsure of any rule.
|
|
119
|
+
2. Pick the source(s): **code** (derive concepts from source, READMEs, docstrings,
|
|
120
|
+
config), **docs/wiki** (distill pages into concepts; cite the originals under
|
|
121
|
+
`# Citations`), **manual** (decisions, playbooks, metrics that live only in
|
|
122
|
+
people's heads).
|
|
123
|
+
3. Choose a domain-based directory layout. One concept per file.
|
|
124
|
+
4. Write each concept from [templates/concept.md](../templates/concept.md): a
|
|
125
|
+
descriptive `type` from the bundle's vocabulary, recommended fields filled,
|
|
126
|
+
cross-links to related concepts written into prose.
|
|
127
|
+
5. Add or refresh `index.md` per directory from
|
|
128
|
+
[templates/index.md](../templates/index.md); for the bundle root use
|
|
129
|
+
[templates/root-index.md](../templates/root-index.md) so it carries
|
|
130
|
+
`okf_version: "0.1"`. Append a dated entry to `log.md`.
|
|
131
|
+
6. **Close out** — walk the Closeout gate below (`validate` + `lint` are part of it,
|
|
132
|
+
see [cli.md](cli.md)) before finishing.
|
|
133
|
+
|
|
134
|
+
### maintain — keep a bundle in sync with reality
|
|
135
|
+
1. **Orient before hunting.** Run `okf index <dir>` (the §6 map — every directory's
|
|
136
|
+
index body, rollups, and listings), read `log.md` (the §7 baseline: what changed
|
|
137
|
+
last), and `okf stats <dir>` (size and shape) *before* you grep. It is the
|
|
138
|
+
cheapest context and it primes the hunt — and it is the only reliable way to
|
|
139
|
+
catch enumeration drift, because **grep cannot find an index entry that is
|
|
140
|
+
missing.** (This is the always-on reflex in [SKILL.md](../SKILL.md).)
|
|
141
|
+
2. **Find *every* affected concept** — the failure mode is fixing only the obvious
|
|
142
|
+
one. Don't rely on reading the whole bundle; that only scales on tiny ones. Grep
|
|
143
|
+
the changed asset's `resource` URI across the bundle, grep its path/name, and use
|
|
144
|
+
`okf graph --json` to pull the concepts that link *to* the ones you're touching.
|
|
145
|
+
Let grep and the graph find them so nothing drifts silently.
|
|
146
|
+
3. Update bodies and `timestamp`; fix or add cross-links; create new concepts for
|
|
147
|
+
new assets; mark retired assets with a `**Deprecation**` note rather than
|
|
148
|
+
silently deleting the context that explains them.
|
|
149
|
+
4. **Update every enumeration that names what you changed — including `index.md`
|
|
150
|
+
bodies**, not just the concept files: a new, renamed, or removed concept changes
|
|
151
|
+
its directory's index listing too. Append a dated `log.md` entry. Step 1's map
|
|
152
|
+
is how you verify this — re-run `okf index` and confirm each listing matches
|
|
153
|
+
reality.
|
|
154
|
+
5. Run `validate`, then `lint` to catch the curation drift the change introduced —
|
|
155
|
+
new orphans, broken citations, dangling index entries. Add `--stale-after`
|
|
156
|
+
(e.g. `90d`) if concepts carry timestamps: freshness is off by default, so a
|
|
157
|
+
plain `lint` will not tell you what the change left stale.
|
|
158
|
+
6. **Review loose files** — run `okf loose <dir>` (the folder-grouped view of
|
|
159
|
+
`lint`'s `unlinked` check): the concepts with **no cross-links in or out**, which
|
|
160
|
+
float in the graph. This is a semantic pass the tool cannot do for you — for each
|
|
161
|
+
floater, judge intent:
|
|
162
|
+
- **should it link out?** the concept relates to others but says so nowhere —
|
|
163
|
+
write the sentence that explains the relationship and put the link in it;
|
|
164
|
+
- **should something link to it?** it is knowledge others should reach by
|
|
165
|
+
following links, not just via an index — add the inbound link from where it
|
|
166
|
+
belongs;
|
|
167
|
+
- **legitimately terminal?** a backlog item, a spec reference, a leaf reachable
|
|
168
|
+
by design only through its index — leave it. **Terminal-by-design is not a
|
|
169
|
+
defect.** Loose ≠ orphan: an index listing makes a file *reachable* (not an
|
|
170
|
+
orphan) but is not a graph edge, so an indexed file can still float here.
|
|
171
|
+
7. **Curate the tag vocabulary** when the pass touched tags, or when `okf tags
|
|
172
|
+
<dir>` shows a long tail of singletons. Run `okf tags <dir> --by area` and
|
|
173
|
+
`--by type` — the grouped view is the analysis; read each group top-down:
|
|
174
|
+
- **twins** — two tags riding the exact same concepts (equal counts sort them
|
|
175
|
+
adjacent). Merge into one unless each genuinely names a different theme.
|
|
176
|
+
- **group-name echoes** — a tag matching its own group's name (a `format` tag
|
|
177
|
+
inside `format/`, an `overview` tag on an Overview). It restates an axis the
|
|
178
|
+
concept already carries; drop it from those concepts.
|
|
179
|
+
- **singletons** — for each, ask: would an existing tag serve? is it an
|
|
180
|
+
anticipated cluster that concepts landing soon will join? is it a deliberate
|
|
181
|
+
marker (`security`, `deprecated`)? Merge, keep, or drop accordingly — a
|
|
182
|
+
count of 1 is a question, never a verdict.
|
|
183
|
+
- **connective tags** — recurring across groups: these are the vocabulary's
|
|
184
|
+
spine. Protect them; prefer merging others *into* them over renaming them,
|
|
185
|
+
because consumers learn these keys and stability is part of their value.
|
|
186
|
+
The trap in this pass is optimizing the numbers instead of the vocabulary:
|
|
187
|
+
you can reach zero singletons by deleting every tag, and perfect cohesion by
|
|
188
|
+
tagging everything alike. The goal is a small set of tags where each one
|
|
189
|
+
either connects or marks — judged, not counted.
|
|
190
|
+
|
|
191
|
+
### consume — use a bundle as context
|
|
192
|
+
1. **Orient first** (the [SKILL.md](../SKILL.md) reflex): `okf index <dir>` maps the
|
|
193
|
+
whole bundle in one pass — every directory's index body, rollups, and listings —
|
|
194
|
+
and `log.md` gives recent history. Then follow links only into the concepts the
|
|
195
|
+
task needs. For a large bundle, `okf graph --json` gives the whole link structure
|
|
196
|
+
at once so you can plan a traversal without opening every file.
|
|
197
|
+
2. Treat broken links as not-yet-written knowledge, not errors.
|
|
198
|
+
3. **Write-back reflex:** if you learn something durable while working — a fact the
|
|
199
|
+
bundle lacks, a link it is missing, a concept that no longer matches reality —
|
|
200
|
+
switch to `maintain` and record it. That reflex is what keeps the bundle alive.
|
|
201
|
+
|
|
202
|
+
## Closeout — the finishing gate
|
|
203
|
+
|
|
204
|
+
`produce` step 6 and `maintain` steps 4–7 both land here: before calling an
|
|
205
|
+
authoring task done, walk this once. It is the repo's "turn every task into a check
|
|
206
|
+
that can fail" discipline, and followed literally it catches the enumeration drift
|
|
207
|
+
grep can't:
|
|
208
|
+
|
|
209
|
+
- **Index enumerations** — every `index.md` that lists what you added, renamed, or
|
|
210
|
+
removed is updated; re-run `okf index` and eyeball each listing against reality.
|
|
211
|
+
Easy to skip, expensive to miss — this is the check that was missing.
|
|
212
|
+
- **`log.md`** — a dated entry, newest first.
|
|
213
|
+
- **Timestamps** bumped on the concepts you touched.
|
|
214
|
+
- **`validate`** — zero §9 errors.
|
|
215
|
+
- **`lint`** — cheap findings cleared; pass `--stale-after` when concepts carry
|
|
216
|
+
timestamps (freshness is off by default).
|
|
217
|
+
- **`loose` review + tag curation** — the two semantic passes (maintain steps 6–7);
|
|
218
|
+
worth a pass in `produce` too on a non-trivial bundle.
|