okf 1.11.0 → 1.12.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 +4 -4
- data/CHANGELOG.md +92 -1
- data/README.md +136 -96
- data/lib/okf/bundle/folder.rb +4 -0
- data/lib/okf/bundle/search.rb +5 -5
- data/lib/okf/bundle/skeleton.rb +241 -0
- data/lib/okf/bundle.rb +18 -13
- data/lib/okf/cli/catalog.rb +5 -5
- data/lib/okf/cli/command.rb +72 -7
- data/lib/okf/cli/graph.rb +115 -9
- data/lib/okf/cli/registry.rb +152 -15
- data/lib/okf/cli/render.rb +3 -2
- data/lib/okf/cli/search.rb +32 -1
- data/lib/okf/cli/server.rb +9 -5
- data/lib/okf/cli/stats.rb +8 -8
- data/lib/okf/cli/tags.rb +1 -1
- data/lib/okf/cli.rb +3 -3
- data/lib/okf/registry.rb +351 -20
- data/lib/okf/render/graph/template.html.erb +211 -7
- data/lib/okf/render/graph.rb +27 -3
- data/lib/okf/server/app.rb +13 -3
- data/lib/okf/server/hub.rb +5 -3
- data/lib/okf/skill/SKILL.md +5 -1
- data/lib/okf/skill/playbooks/menu.md +2 -1
- data/lib/okf/skill/playbooks/refine.md +26 -0
- data/lib/okf/skill/reference/cli.md +76 -19
- data/lib/okf/version.rb +1 -1
- data/lib/okf.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9a83101e62e3b3bc97d7351580d50ecc017be391a5edbde2e8f52388de529111
|
|
4
|
+
data.tar.gz: 040be5295642da56cbeed342424872469d1c2b15efcb1b477f10076d7c90fafc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 47fb84d8dffc04eee30eb65adfaca756ae43315e2d152e62692084a5bd04c6a7992529d243b2375412a8339a55db891c3ae18d679e171d5709e9426b93686047
|
|
7
|
+
data.tar.gz: 30390e1eecc1570b28531c374b21200309630aad87f821a7c3f25b631ca5285e03b91baab9048f69127931a09368da1ab38a089fc9bc25473c05da3c0fadfe2b
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,97 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.12.0] - 2026-07-24
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`okf graph --traffic`** — the link graph read one grain coarser. `--hubs`
|
|
13
|
+
measures concepts, but the refine playbook's directory judgements ("does this
|
|
14
|
+
directory prune? a concern, or a container?") had nothing measured at their
|
|
15
|
+
grain. `--traffic` collapses each concept into its directory and the links
|
|
16
|
+
between two directories into one weighted arc, so every row carries its
|
|
17
|
+
internal / out / in traffic and a **cohesion** — its internal share of that
|
|
18
|
+
total. That is cohesion versus coupling on a knowledge tree: near-zero cohesion
|
|
19
|
+
under heavy inbound is a shared vocabulary doing its job, heavy outbound with
|
|
20
|
+
nothing back is a projection wearing a directory. The rows sort by cohesion
|
|
21
|
+
ascending, so the directories with a case to answer come first, and a directory
|
|
22
|
+
with no traffic at all prints `—` rather than a `0%` it did not earn. The arc
|
|
23
|
+
**cut** is fitted to the bundle, not fixed — at weight 3, ten bundles ranged
|
|
24
|
+
from 2 arcs to 136 — and `--cut N` overrides it; cohesion is computed over
|
|
25
|
+
*every* arc regardless, so narrowing the drawn picture never moves the
|
|
26
|
+
evidence. JSON: `{ bundle, cut, fitted, dirs, arcs, total_arcs }`. The pure
|
|
27
|
+
model underneath is `Bundle::Skeleton` — concepts folded to directories, links
|
|
28
|
+
to weighted arcs, every edge tagged with the cut it survives (a local-degree
|
|
29
|
+
sparsifier, union rule, so no linked concept is ever stranded) — and it does no
|
|
30
|
+
I/O and draws nothing: it names a cut rather than taking one, so both the graph
|
|
31
|
+
page and the CLI narrow the same emission their own way.
|
|
32
|
+
- **The graph page draws links in three amounts, and opens dense on its spine.**
|
|
33
|
+
227 links over 47 concepts at degree 9.7 is unreadable because of its arrows,
|
|
34
|
+
not its dots — so links become a layer: **every** link, the **spine** (each
|
|
35
|
+
concept's strongest edge — the Skeleton's `keep_at===0` set, chosen so it
|
|
36
|
+
touches every linked concept), or **none**, with a selected concept's own links
|
|
37
|
+
always shown in full. A dense bundle now opens on its spine rather than greeting
|
|
38
|
+
the reader with the thicket; the trigger is undirected degree above a floor set
|
|
39
|
+
between a tree's ~2 and the 9.7 that drove it, and `--map` overrides to none
|
|
40
|
+
with the directories boxed. Above 800 edges the first layout runs on the spine
|
|
41
|
+
alone and the rest arrive a frame later with no re-layout — **6.25 s → 3.29 s**
|
|
42
|
+
on 414 concepts, nothing on screen moving. Proven in both render modes on a
|
|
43
|
+
committed 110-concept / 880-link fixture, the only one over both floors.
|
|
44
|
+
- **Registry groups — a named, recursive set of bundles.** A group is a registry
|
|
45
|
+
slug that names a list of members (bundle *or* group slugs, so they nest) and
|
|
46
|
+
resolves recursively, path-deduped, to its bundle leaves. `okf registry group
|
|
47
|
+
<slug> <@member…>` creates one or adds to it, `ungroup` removes members (and
|
|
48
|
+
emptying a group deletes it), and `del`/`rename` now span a group slug too —
|
|
49
|
+
one name cascades across every member list, one `del` cascade-drops the slug and
|
|
50
|
+
deletes any group it empties. Groups live in their own list in the registry
|
|
51
|
+
JSON, so the first-is-default rule and the `File.directory?` guards never meet a
|
|
52
|
+
pathless entry. `okf search @backend` merges the members into one ranking and
|
|
53
|
+
`okf server @backend` mounts each (the first at `/`), both skipping a vanished
|
|
54
|
+
member with a note, exactly as `@all` does. Every single-bundle verb **refuses**
|
|
55
|
+
a `@group` (exit 2) — the same rule that refuses a second bundle, through the
|
|
56
|
+
same `resolve_registered` seam.
|
|
57
|
+
- **`okf registry init`** — create a project-local `.okf-registry.json` in the
|
|
58
|
+
current directory. Once it exists, okf discovers it by walking up from the
|
|
59
|
+
working directory, and every registry operation — and every `@slug` — resolves
|
|
60
|
+
through it in place of the global `$OKF_HOME` registry, so a bare `okf server`
|
|
61
|
+
inside a repo serves that repo's bundles with no global setup. The nearest one
|
|
62
|
+
on the path wins (nested registries resolve nearest-first), `okf registry list`
|
|
63
|
+
names the local file it found, and `OKF_NO_DISCOVERY=1` forces the global one —
|
|
64
|
+
the escape hatch for a fixed-cwd caller (CI, a tool).
|
|
65
|
+
- **A local registry stores portable, relative paths.** A bundle inside the
|
|
66
|
+
registry's own tree is written relative to the `.okf-registry.json`, so the file
|
|
67
|
+
can be committed and travels with the repo — a checkout on another machine, or a
|
|
68
|
+
container that mounts it, resolves the same bundles unchanged. A bundle outside
|
|
69
|
+
the tree keeps an absolute path (it cannot travel). Paths still read back
|
|
70
|
+
absolute everywhere the CLI reports them; the relative form lives only on disk,
|
|
71
|
+
and an existing absolute local entry migrates to relative on its next write. The
|
|
72
|
+
global `$OKF_HOME` registry is unchanged — it stores absolute paths as before.
|
|
73
|
+
|
|
74
|
+
### Changed
|
|
75
|
+
|
|
76
|
+
- **The derived `area` field is renamed `top_dir`** — the first-path-segment
|
|
77
|
+
rollup the catalog, search, `stats`, and `graph --hubs` carry. `area` was never
|
|
78
|
+
the OKF spec's word (the spec speaks only of `dir`), so the rollup now names
|
|
79
|
+
itself in the spec's vocabulary: it is the `dir` at the top level. The `--json`
|
|
80
|
+
keys move with it — catalog/search rows carry `top_dir` in place of `area`,
|
|
81
|
+
`stats` emits `top_dirs`/`by_top_dir`, and `graph --hubs` emits
|
|
82
|
+
`top_dir`/`by_top_dir`. The **deprecated `--area`/`--by area` input flags are
|
|
83
|
+
unchanged** — they still warn and map to `--dir`/`--by dir`, and now source the
|
|
84
|
+
renamed field internally. No behavior changes; the well-homed-hub numbers are
|
|
85
|
+
identical.
|
|
86
|
+
|
|
87
|
+
### Fixed
|
|
88
|
+
|
|
89
|
+
- **A local-registry server preserves its relative-path anchor across a
|
|
90
|
+
re-open.** The hub re-read its boot registry with `OKF::Registry.new(path)`,
|
|
91
|
+
which drops the `relative_base` a discovered `.okf-registry.json` carries — so
|
|
92
|
+
on a project-local server the Bundles panel matched each mounted bundle's
|
|
93
|
+
absolute root against the re-read entry's *relative* path, missed, and drew
|
|
94
|
+
every in-tree bundle as "folder is gone", while a browser add flattened the new
|
|
95
|
+
bundle to an absolute path, undoing the portability relative storage exists for.
|
|
96
|
+
`Registry#reopen` re-reads the same file anchored the same way, and both hub
|
|
97
|
+
re-open sites use it.
|
|
98
|
+
|
|
8
99
|
## [1.11.0] - 2026-07-22
|
|
9
100
|
|
|
10
101
|
### Added
|
|
@@ -205,7 +296,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
205
296
|
rendered `(root)` for humans — and "cluster" stays prose for what a dir
|
|
206
297
|
groups. Both deprecated spellings keep their **old behavior exactly** and warn
|
|
207
298
|
once per run on stderr (`--json` on stdout is unaffected); they go in a later
|
|
208
|
-
release
|
|
299
|
+
release.
|
|
209
300
|
|
|
210
301
|
## [1.10.0] - 2026-07-21
|
|
211
302
|
|
data/README.md
CHANGED
|
@@ -227,72 +227,26 @@ okf server .
|
|
|
227
227
|
Images are published for `linux/amd64` and `linux/arm64` on
|
|
228
228
|
[ghcr.io](https://github.com/serradura/okf-gem/pkgs/container/okf).
|
|
229
229
|
|
|
230
|
-
##
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
(
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
okf registry list | set | del | default | rename # name your bundles (see below)
|
|
251
|
-
okf skill <dest> # install the companion agent skill
|
|
252
|
-
okf --version
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
Exit codes: `0` success, `1` non-conformant bundle (or a `lint --fail-on`
|
|
256
|
-
threshold crossed), `2` usage error. Every flag is in `okf <verb> --help` and in
|
|
257
|
-
[the docs](https://okfgem.com/docs/).
|
|
258
|
-
|
|
259
|
-
```bash
|
|
260
|
-
$ okf validate docs
|
|
261
|
-
OKF v0.1 conformance — docs
|
|
262
|
-
concepts: 37 index.md: 10 log.md: 1
|
|
263
|
-
! warn features/link-suggestions.md: cross-link target not found: `/graph-view.md` (tolerated under §5.3)
|
|
264
|
-
…
|
|
265
|
-
✓ conformant (33 warning(s))
|
|
266
|
-
|
|
267
|
-
$ okf server docs
|
|
268
|
-
serving 37 concepts at http://127.0.0.1:8808 (Ctrl-C to stop)
|
|
269
|
-
|
|
270
|
-
$ okf render docs > public/index.html # the same page, static — host it anywhere
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
### Reading a big bundle a level at a time
|
|
274
|
-
|
|
275
|
-
A few hundred concepts is a map nobody reads whole, so `index` and `dirs` descend
|
|
276
|
-
instead of dumping. `--dir` takes a directory **and everything under it**,
|
|
277
|
-
`--depth N` bounds how far below that it goes, and the two compose the way you
|
|
278
|
-
actually walk a tree:
|
|
279
|
-
|
|
280
|
-
```bash
|
|
281
|
-
okf dirs @handbook # the shape: every dir, what it holds directly and below
|
|
282
|
-
okf index @handbook --depth 1 --no-body # the top of the map, no prose
|
|
283
|
-
okf index @handbook --dir platform/api # now open one branch — with the chain that places it
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
Naming a `--dir` brings its ancestors along, marked `↑`, so a branch is never
|
|
287
|
-
shown adrift of the context that says what it is — the root `index.md`'s prose
|
|
288
|
-
first among it.
|
|
289
|
-
|
|
290
|
-
For an agent the saving is the whole point. On a 400-concept bundle the full
|
|
291
|
-
`okf index --json` is 313 KB; the skeleton it orients on is 2.8 KB:
|
|
292
|
-
|
|
293
|
-
```bash
|
|
294
|
-
okf index @handbook --json --depth 1 --except body,listing
|
|
295
|
-
```
|
|
230
|
+
## Where to go next
|
|
231
|
+
|
|
232
|
+
Installed. The rest of this page is each surface the gem gives you over a bundle,
|
|
233
|
+
in the order most people meet them:
|
|
234
|
+
|
|
235
|
+
- **[The graph](#the-graph)** — the whole bundle on one page, live or baked into a
|
|
236
|
+
single HTML file you can host anywhere. Start here if you want to *see* it.
|
|
237
|
+
- **[Agent skill](#agent-skill)** — the verbs your agent runs to author, maintain
|
|
238
|
+
and answer from a bundle, so you stay the editor rather than the typist.
|
|
239
|
+
- **[Claude Code plugin](#claude-code-plugin)** — that skill, a slash command and a
|
|
240
|
+
post-edit curation hook, in two lines.
|
|
241
|
+
- **[Command line](#command-line)** — every view as scannable text or as JSON, with
|
|
242
|
+
exit codes stable enough to gate CI on.
|
|
243
|
+
- **[Library](#library)** — `OKF::Bundle` in your own Ruby, and the graph as a Rack
|
|
244
|
+
app you can mount in an app you already have.
|
|
245
|
+
- **[Extending okf](#extending-okf-and-running-it-safely)** — ship a verb as a gem,
|
|
246
|
+
and what the page does and does not trust in a bundle you did not write.
|
|
247
|
+
|
|
248
|
+
Full reference for every verb and flag lives in
|
|
249
|
+
**[the docs](https://okfgem.com/docs/)**.
|
|
296
250
|
|
|
297
251
|
## The graph
|
|
298
252
|
|
|
@@ -335,6 +289,24 @@ okf search @all rate limit # ranked retrieval across every register
|
|
|
335
289
|
okf server # no args: the whole registry behind one hub
|
|
336
290
|
```
|
|
337
291
|
|
|
292
|
+
Related bundles can share a name: `okf registry group backend @handbook @runbooks`
|
|
293
|
+
makes `@backend` stand for the set (members can be groups too, so they nest), and
|
|
294
|
+
`okf search @backend rate limit` or `okf server @backend` then targets all of them
|
|
295
|
+
at once — a durable subset for the two verbs that take several bundles.
|
|
296
|
+
|
|
297
|
+
The registry lives under `$OKF_HOME` (default `~/.okf`) — one per user. For one
|
|
298
|
+
scoped to a single project instead, `okf registry init` drops a
|
|
299
|
+
`.okf-registry.json` in the current directory; okf then discovers it by walking up
|
|
300
|
+
from wherever you run, and every registry op — and every `@slug` — resolves through
|
|
301
|
+
it in place of the global one. So a bare `okf server` inside that repo serves *its*
|
|
302
|
+
bundles with no `$OKF_HOME` setup. The nearest registry wins, and
|
|
303
|
+
`OKF_NO_DISCOVERY=1` forces the global one.
|
|
304
|
+
|
|
305
|
+
Commit that file and it travels with the repo: a bundle under the project root is
|
|
306
|
+
stored relative to the registry, so a checkout on another machine — or a container
|
|
307
|
+
that mounts the repo — resolves the same bundles unchanged. (Bundles outside the
|
|
308
|
+
tree keep absolute paths, which do not travel.)
|
|
309
|
+
|
|
338
310
|
Behind the hub each bundle mounts at `/b/<slug>/`, `/b/` lists them all, and the
|
|
339
311
|
`⌘/Ctrl-K` palette both switches bundles and **searches every one at once** — type
|
|
340
312
|
a few words and the matching concepts appear with their bundle and a snippet, from
|
|
@@ -350,7 +322,8 @@ public one.
|
|
|
350
322
|
|
|
351
323
|
The gem carries the [companion OKF agent skill](.okf/capabilities/agent-skill.md):
|
|
352
324
|
a `SKILL.md` plus reference and template files that teach a coding agent to
|
|
353
|
-
author, maintain, and consume OKF bundles and to drive the
|
|
325
|
+
author, maintain, and consume OKF bundles and to drive the
|
|
326
|
+
[commands below](#command-line).
|
|
354
327
|
Because the skill ships inside the gem, installing the gem already puts the skill
|
|
355
328
|
on your machine, and the skill's CLI reference can never drift from the
|
|
356
329
|
executable it was released with.
|
|
@@ -390,6 +363,99 @@ okf skill .agents # agent-agnostic -> .agents/skills/okf
|
|
|
390
363
|
The resolved directory must be empty unless you pass `--force`, so a customized
|
|
391
364
|
skill is never clobbered.
|
|
392
365
|
|
|
366
|
+
## Claude Code plugin
|
|
367
|
+
|
|
368
|
+
This repository doubles as a Claude Code plugin marketplace, so the whole
|
|
369
|
+
toolchain installs with two commands inside Claude Code:
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
/plugin marketplace add serradura/okf-gem
|
|
373
|
+
/plugin install okf@okfgem
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
The plugin carries three pieces: the [`okf` skill](#agent-skill) above;
|
|
377
|
+
**`/okf:gem`**, a front door that hands its arguments to the skill unchanged (no
|
|
378
|
+
arguments: it orients on your bundle and recommends the next move, never
|
|
379
|
+
auto-runs); and a **curation hook** that runs `okf validate` + `okf lint` after
|
|
380
|
+
every edit inside a bundle and returns the findings as context. The checks are
|
|
381
|
+
the CLI's own, so the feedback is deterministic.
|
|
382
|
+
|
|
383
|
+
The hook stays silent outside bundles, and it is config-free to switch off:
|
|
384
|
+
`OKF_CURATE_DISABLED=1` turns it off, `OKF_CURATE_QUIET=1` keeps the findings
|
|
385
|
+
without the install suggestion, and an `<!-- okf-disable -->` comment skips one
|
|
386
|
+
file.
|
|
387
|
+
|
|
388
|
+
Prefer no plugin? `gem install okf && okf skill .claude` installs the skill
|
|
389
|
+
alone, and the skill itself instructs the agent to run the same checks after
|
|
390
|
+
editing a bundle.
|
|
391
|
+
|
|
392
|
+
## Command line
|
|
393
|
+
|
|
394
|
+
These verbs are written to be read by an **agent first and a person second** —
|
|
395
|
+
that is what the skill drives, with no wrapper in between. Every read verb takes
|
|
396
|
+
`--json`, the list views project down to the fields you ask for
|
|
397
|
+
(`--fields`/`--except`), so nothing pays for output it will not read, and the
|
|
398
|
+
exit codes are stable enough to branch on in CI. The same commands render as
|
|
399
|
+
scannable plain text when a human is the one looking.
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
okf validate <dir|@slug> # is this legal OKF?
|
|
403
|
+
okf lint <dir|@slug> [--fail-on warn] # is it navigable, complete, fresh?
|
|
404
|
+
okf loose <dir|@slug> # concepts with no links in or out
|
|
405
|
+
okf search <dir|@slug…|@all> <term…> # ranked retrieval; @all spans every bundle
|
|
406
|
+
okf index <dir|@slug> [--dir D] [--depth N] # the §6 map: index bodies, rollups, listings
|
|
407
|
+
okf dirs <dir|@slug> [--dir D] [--depth N] # the shape: every directory and what it holds
|
|
408
|
+
okf catalog | files | tags | types | stats <dir|@slug> # the browser views, on the CLI
|
|
409
|
+
okf graph <dir|@slug> [--hubs] [--traffic] # the raw graph; --hubs ranks concepts, --traffic dirs
|
|
410
|
+
okf server [DIR|@slug…] [-p PORT] [--bind ADDR] # the live graph: one bundle, or all of them
|
|
411
|
+
okf render <dir|@slug> [-o FILE] # the same page as one static, self-contained file
|
|
412
|
+
okf registry init | list | set | del | default | rename | group | ungroup # name & group your bundles; @slug works anywhere
|
|
413
|
+
okf skill <dest> # install the companion agent skill
|
|
414
|
+
okf --version
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Exit codes: `0` success, `1` non-conformant bundle (or a `lint --fail-on`
|
|
418
|
+
threshold crossed), `2` usage error. Every flag is in `okf <verb> --help` and in
|
|
419
|
+
[the docs](https://okfgem.com/docs/).
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
$ okf validate docs
|
|
423
|
+
OKF v0.1 conformance — docs
|
|
424
|
+
concepts: 37 index.md: 10 log.md: 1
|
|
425
|
+
! warn features/link-suggestions.md: cross-link target not found: `/graph-view.md` (tolerated under §5.3)
|
|
426
|
+
…
|
|
427
|
+
✓ conformant (33 warning(s))
|
|
428
|
+
|
|
429
|
+
$ okf server docs
|
|
430
|
+
serving 37 concepts at http://127.0.0.1:8808 (Ctrl-C to stop)
|
|
431
|
+
|
|
432
|
+
$ okf render docs > public/index.html # the same page, static — host it anywhere
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Reading a big bundle a level at a time
|
|
436
|
+
|
|
437
|
+
A few hundred concepts is a map nobody reads whole, so `index` and `dirs` descend
|
|
438
|
+
instead of dumping. `--dir` takes a directory **and everything under it**,
|
|
439
|
+
`--depth N` bounds how far below that it goes, and the two compose the way you
|
|
440
|
+
actually walk a tree:
|
|
441
|
+
|
|
442
|
+
```bash
|
|
443
|
+
okf dirs @handbook # the shape: every dir, what it holds directly and below
|
|
444
|
+
okf index @handbook --depth 1 --no-body # the top of the map, no prose
|
|
445
|
+
okf index @handbook --dir platform/api # now open one branch — with the chain that places it
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Naming a `--dir` brings its ancestors along, marked `↑`, so a branch is never
|
|
449
|
+
shown adrift of the context that says what it is — the root `index.md`'s prose
|
|
450
|
+
first among it.
|
|
451
|
+
|
|
452
|
+
For an agent the saving is the whole point. On a 400-concept bundle the full
|
|
453
|
+
`okf index --json` is 313 KB; the skeleton it orients on is 2.8 KB:
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
okf index @handbook --json --depth 1 --except body,listing
|
|
457
|
+
```
|
|
458
|
+
|
|
393
459
|
## Library
|
|
394
460
|
|
|
395
461
|
`require "okf"` gives you the whole thing as Ruby objects — two layers: pure
|
|
@@ -412,17 +478,17 @@ OKF::Server::App.new(folder) # => a Rack app: the interactive graph, mountab
|
|
|
412
478
|
|
|
413
479
|
That last line is the point of the Rack app: the graph mounts inside an app you
|
|
414
480
|
already have, auth included. The [Rails guide](https://okfgem.com/docs/guides/rails/)
|
|
415
|
-
walks it, and the [library API](.
|
|
481
|
+
walks it, and the [library API](https://okfgem.com/docs/library/) covers
|
|
416
482
|
the pure layer, the writer, and the lower-level pieces.
|
|
417
483
|
|
|
418
484
|
### validate and lint are two different questions
|
|
419
485
|
|
|
420
|
-
`validate` (the [conformance validator](.
|
|
486
|
+
`validate` (the [conformance validator](https://okfgem.com/docs/cli/validate/)) asks
|
|
421
487
|
_"is this legal OKF?"_ and implements the spec's
|
|
422
488
|
[§9](lib/okf/skill/reference/SPEC.md#9-conformance) exactly — which means it is
|
|
423
489
|
*forbidden* to reject a bundle for a broken link or a missing optional field.
|
|
424
490
|
|
|
425
|
-
`lint` (the [curation linter](.
|
|
491
|
+
`lint` (the [curation linter](https://okfgem.com/docs/cli/lint/)) asks the
|
|
426
492
|
complementary question, _"is this well-curated, navigable, trustworthy?"_, over
|
|
427
493
|
exactly those tolerated things: reachability, backlog, completeness, freshness,
|
|
428
494
|
provenance, hygiene. It is advisory and exits `0` even with findings unless you
|
|
@@ -447,32 +513,6 @@ treat an unfamiliar bundle the way you would treat any document from a source yo
|
|
|
447
513
|
do not know. Full write-up:
|
|
448
514
|
[server trust boundary](.okf/design/server-trust-boundary.md).
|
|
449
515
|
|
|
450
|
-
## Claude Code plugin
|
|
451
|
-
|
|
452
|
-
This repository doubles as a Claude Code plugin marketplace, so the whole
|
|
453
|
-
toolchain installs with two commands inside Claude Code:
|
|
454
|
-
|
|
455
|
-
```
|
|
456
|
-
/plugin marketplace add serradura/okf-gem
|
|
457
|
-
/plugin install okf@okfgem
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
The plugin carries three pieces: the [`okf` skill](#agent-skill) above;
|
|
461
|
-
**`/okf:gem`**, a front door that hands its arguments to the skill unchanged (no
|
|
462
|
-
arguments: it orients on your bundle and recommends the next move, never
|
|
463
|
-
auto-runs); and a **curation hook** that runs `okf validate` + `okf lint` after
|
|
464
|
-
every edit inside a bundle and returns the findings as context. The checks are
|
|
465
|
-
the CLI's own, so the feedback is deterministic.
|
|
466
|
-
|
|
467
|
-
The hook stays silent outside bundles, and it is config-free to switch off:
|
|
468
|
-
`OKF_CURATE_DISABLED=1` turns it off, `OKF_CURATE_QUIET=1` keeps the findings
|
|
469
|
-
without the install suggestion, and an `<!-- okf-disable -->` comment skips one
|
|
470
|
-
file.
|
|
471
|
-
|
|
472
|
-
Prefer no plugin? `gem install okf && okf skill .claude` installs the skill
|
|
473
|
-
alone, and the skill itself instructs the agent to run the same checks after
|
|
474
|
-
editing a bundle.
|
|
475
|
-
|
|
476
516
|
## Development
|
|
477
517
|
|
|
478
518
|
```bash
|
data/lib/okf/bundle/folder.rb
CHANGED
data/lib/okf/bundle/search.rb
CHANGED
|
@@ -279,7 +279,7 @@ module OKF
|
|
|
279
279
|
end
|
|
280
280
|
|
|
281
281
|
# Ranked match rows, catalog-style identity plus where the terms hit:
|
|
282
|
-
# [{ slug:, id:, title:, type:, dir:,
|
|
282
|
+
# [{ slug:, id:, title:, type:, dir:, top_dir:, tags:, matched: [field, …], score:, snippet: }, …]
|
|
283
283
|
# ordered by score descending, then slug, then id. `slug` is present only
|
|
284
284
|
# when searching across bundles. No terms means no matches.
|
|
285
285
|
def results
|
|
@@ -367,7 +367,7 @@ module OKF
|
|
|
367
367
|
title: (concept.title || concept.id).to_s,
|
|
368
368
|
type: concept.type.to_s,
|
|
369
369
|
dir: OKF.dir_of(concept.id),
|
|
370
|
-
|
|
370
|
+
top_dir: top_dir_of(concept.id),
|
|
371
371
|
tags: Array(concept.tags).map(&:to_s),
|
|
372
372
|
matched: matched,
|
|
373
373
|
score: score.round(4),
|
|
@@ -421,9 +421,9 @@ module OKF
|
|
|
421
421
|
end
|
|
422
422
|
end
|
|
423
423
|
|
|
424
|
-
# A concept's top-level
|
|
425
|
-
#
|
|
426
|
-
def
|
|
424
|
+
# A concept's top-level dir, mirroring the catalog's definition — the first
|
|
425
|
+
# path segment. OKF.dir_of keeps the levels this one rolls up.
|
|
426
|
+
def top_dir_of(id)
|
|
427
427
|
id.include?("/") ? id.split("/").first : "(root)"
|
|
428
428
|
end
|
|
429
429
|
end
|