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.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.okf/capabilities/agent-skill.md +46 -0
  3. data/.okf/capabilities/graph-server.md +60 -0
  4. data/.okf/capabilities/index.md +20 -0
  5. data/.okf/capabilities/library-api.md +67 -0
  6. data/.okf/capabilities/linter.md +49 -0
  7. data/.okf/capabilities/read-views.md +84 -0
  8. data/.okf/capabilities/validator.md +40 -0
  9. data/.okf/cli.md +52 -0
  10. data/.okf/design/core-shell-split.md +58 -0
  11. data/.okf/design/index.md +10 -0
  12. data/.okf/design/ruby-floor.md +45 -0
  13. data/.okf/design/runtime-dependencies.md +44 -0
  14. data/.okf/design/server-trust-boundary.md +35 -0
  15. data/.okf/format/citations.md +33 -0
  16. data/.okf/format/cross-links.md +52 -0
  17. data/.okf/format/frontmatter.md +38 -0
  18. data/.okf/format/index.md +9 -0
  19. data/.okf/format/okf-format.md +43 -0
  20. data/.okf/index.md +18 -0
  21. data/.okf/log.md +9 -0
  22. data/.okf/model/bundle.md +38 -0
  23. data/.okf/model/concept.md +44 -0
  24. data/.okf/model/graph.md +44 -0
  25. data/.okf/model/index.md +8 -0
  26. data/.okf/overview.md +66 -0
  27. data/CHANGELOG.md +54 -0
  28. data/CODE_OF_CONDUCT.md +10 -0
  29. data/LICENSE.txt +201 -0
  30. data/NOTICE +10 -0
  31. data/README.md +276 -0
  32. data/exe/okf +6 -0
  33. data/lib/okf/bundle/folder.rb +94 -0
  34. data/lib/okf/bundle/graph.rb +118 -0
  35. data/lib/okf/bundle/linter/report.rb +56 -0
  36. data/lib/okf/bundle/linter.rb +416 -0
  37. data/lib/okf/bundle/reader.rb +60 -0
  38. data/lib/okf/bundle/validator/result.rb +35 -0
  39. data/lib/okf/bundle/validator.rb +131 -0
  40. data/lib/okf/bundle/writer.rb +137 -0
  41. data/lib/okf/bundle.rb +216 -0
  42. data/lib/okf/cli.rb +910 -0
  43. data/lib/okf/concept/file.rb +63 -0
  44. data/lib/okf/concept.rb +101 -0
  45. data/lib/okf/markdown/citations.rb +49 -0
  46. data/lib/okf/markdown/frontmatter.rb +55 -0
  47. data/lib/okf/markdown/links.rb +98 -0
  48. data/lib/okf/path.rb +34 -0
  49. data/lib/okf/server/app.rb +120 -0
  50. data/lib/okf/server/graph.rb +112 -0
  51. data/lib/okf/server/runner.rb +78 -0
  52. data/lib/okf/server/templates/graph.html.erb +803 -0
  53. data/lib/okf/skill/SKILL.md +133 -0
  54. data/lib/okf/skill/reference/APACHE-2.0.txt +202 -0
  55. data/lib/okf/skill/reference/SPEC.md +460 -0
  56. data/lib/okf/skill/reference/authoring.md +218 -0
  57. data/lib/okf/skill/reference/cli.md +196 -0
  58. data/lib/okf/skill/templates/concept.md +24 -0
  59. data/lib/okf/skill/templates/index.md +8 -0
  60. data/lib/okf/skill/templates/log.md +6 -0
  61. data/lib/okf/skill/templates/root-index.md +12 -0
  62. data/lib/okf/skill.rb +82 -0
  63. data/lib/okf/version.rb +5 -0
  64. data/lib/okf.rb +55 -0
  65. 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.