okf 2.0.0 → 2.1.1
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/.okf/capabilities/agent-skill.md +112 -0
- data/.okf/capabilities/bundles-manager.md +133 -0
- data/.okf/capabilities/graph-server.md +678 -0
- data/.okf/capabilities/index.md +26 -0
- data/.okf/capabilities/library-api.md +82 -0
- data/.okf/capabilities/linter.md +83 -0
- data/.okf/capabilities/read-views.md +228 -0
- data/.okf/capabilities/render.md +66 -0
- data/.okf/capabilities/search.md +295 -0
- data/.okf/capabilities/validator.md +60 -0
- data/.okf/cli.md +193 -0
- data/.okf/design/browser-tests.md +211 -0
- data/.okf/design/core-shell-split.md +73 -0
- data/.okf/design/index.md +17 -0
- data/.okf/design/integration-first.md +140 -0
- data/.okf/design/packaging.md +65 -0
- data/.okf/design/ruby-floor.md +53 -0
- data/.okf/design/runtime-dependencies.md +82 -0
- data/.okf/design/search-engines.md +154 -0
- data/.okf/design/server-trust-boundary.md +139 -0
- data/.okf/index.md +40 -0
- data/.okf/log.md +662 -0
- data/.okf/model/bundle.md +47 -0
- data/.okf/model/concept.md +75 -0
- data/.okf/model/graph.md +59 -0
- data/.okf/model/index.md +9 -0
- data/.okf/model/skeleton.md +76 -0
- data/.okf/overview.md +87 -0
- data/.okf/registry.md +265 -0
- data/.okf/structure/format-layer.md +59 -0
- data/.okf/structure/index.md +22 -0
- data/.okf/structure/search.md +53 -0
- data/.okf/structure/the-analysers.md +60 -0
- data/.okf/structure/the-cli.md +99 -0
- data/.okf/structure/the-disk-shell.md +67 -0
- data/.okf/structure/the-model.md +81 -0
- data/.okf/structure/the-server.md +74 -0
- data/.okf/structure/the-skill.md +52 -0
- data/.okf/testing/adding-a-verb.md +76 -0
- data/.okf/testing/index.md +12 -0
- data/.okf/testing/the-harness.md +45 -0
- data/CHANGELOG.md +83 -16
- data/README.md +205 -21
- data/lib/okf/cli.rb +20 -2
- data/lib/okf/skill/SKILL.md +15 -7
- data/lib/okf/skill/playbooks/maintain.md +3 -1
- data/lib/okf/skill/playbooks/produce.md +4 -2
- data/lib/okf/skill/reference/authoring.md +23 -26
- data/lib/okf/skill/reference/cli/checks.md +171 -0
- data/lib/okf/skill/reference/cli/graph.md +49 -0
- data/lib/okf/skill/reference/cli/map.md +98 -0
- data/lib/okf/skill/reference/cli/registry.md +70 -0
- data/lib/okf/skill/reference/cli/search.md +130 -0
- data/lib/okf/skill/reference/cli/serve.md +83 -0
- data/lib/okf/skill/reference/cli/views.md +59 -0
- data/lib/okf/skill/reference/cli.md +33 -603
- data/lib/okf/skill/reference/spec-map.md +32 -0
- data/lib/okf/version.rb +1 -1
- metadata +54 -5
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Component
|
|
3
|
+
title: The test harness
|
|
4
|
+
description: One base class for the whole suite — plain Minitest plus `test "..."` and block setup/teardown — and it runs on 2.4, so the gem's API floor binds the tests exactly as it binds `lib/`.
|
|
5
|
+
resource: gems/okf/test/test_helper.rb
|
|
6
|
+
tags: [testing, minitest, ruby-floor]
|
|
7
|
+
generated:
|
|
8
|
+
by: human:maintainer
|
|
9
|
+
at: 2026-08-19T12:00:00Z
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# One base class
|
|
13
|
+
|
|
14
|
+
Every test in this gem subclasses `OKF::TestCase`, defined in
|
|
15
|
+
`test/test_helper.rb`. It is plain Minitest with two pieces of sugar:
|
|
16
|
+
|
|
17
|
+
* `test "a sentence" do … end` instead of `def test_a_sentence`, so a failure
|
|
18
|
+
names the behaviour in prose rather than in snake case;
|
|
19
|
+
* block `setup` / `teardown`, which compose rather than requiring `super`.
|
|
20
|
+
|
|
21
|
+
Nothing else is the base class. A test that reaches for `Minitest::Test`
|
|
22
|
+
directly loses both and reads unlike its neighbours, which is the whole reason
|
|
23
|
+
the sugar exists — the three siblings each ported the same class for the same
|
|
24
|
+
reason, so the suites read alike across the monorepo.
|
|
25
|
+
|
|
26
|
+
# It runs on 2.4, so the floor binds it
|
|
27
|
+
|
|
28
|
+
The suite runs on every supported Ruby, 2.4 included. That makes the
|
|
29
|
+
[Ruby floor](../design/ruby-floor.md)'s forbidden-API list a rule about `test/`
|
|
30
|
+
as much as about `lib/` — a `filter_map` in a test fails the floor container
|
|
31
|
+
exactly as one in a source file does, and RuboCop will not catch either.
|
|
32
|
+
|
|
33
|
+
SimpleCov is the one exception, and it is conditional rather than absent: it
|
|
34
|
+
needs 2.5+, so `test_helper.rb` loads it inside a `begin`/`rescue` and the suite
|
|
35
|
+
simply runs without coverage where it cannot load. Coverage is a reporting
|
|
36
|
+
convenience; the floor is a contract, and the contract wins.
|
|
37
|
+
|
|
38
|
+
# What a test may assume about the disk
|
|
39
|
+
|
|
40
|
+
Fixtures are real directories under `test/fixtures/`, not mocks. A branch that
|
|
41
|
+
no fixture can reach is a branch nobody has ever proven, so the answer to an
|
|
42
|
+
unreachable path is a new fixture rather than a bent assertion — the general
|
|
43
|
+
form of that obligation is `@okf-eco design/how-a-change-is-proven`, and how the
|
|
44
|
+
critical layer is organised is
|
|
45
|
+
[integration first](../design/integration-first.md).
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,71 @@ 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
|
+
## [2.1.1] - 2026-08-20
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **The package metadata follows the `gems/` move and the repository rename.**
|
|
13
|
+
Two URLs on the package page were about to be wrong at once. `changelog_uri`
|
|
14
|
+
named `blob/main/okf/CHANGELOG.md`, a path that stopped existing when the
|
|
15
|
+
four gems moved under `gems/`; `homepage` named `serradura/okf-gem`, and the
|
|
16
|
+
repository is now **`serradura/okf`** — the name the command has had all
|
|
17
|
+
along. rubygems.org serves whatever the last release published, so neither
|
|
18
|
+
corrects itself: only a release republishes metadata, and this is that
|
|
19
|
+
release. Both land in one round rather than two, which is the whole reason
|
|
20
|
+
the rename waited for the paths to stop moving.
|
|
21
|
+
|
|
22
|
+
`homepage_uri`, `source_code_uri` and `changelog_uri` are all derived from
|
|
23
|
+
`homepage`, so one line moves four pieces of this gem's metadata. GitHub
|
|
24
|
+
redirects the old URLs permanently, so anything already published keeps
|
|
25
|
+
resolving.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **The gem ships a file-level map of itself, at `.okf/`.** `structure/` names
|
|
30
|
+
every one of the fifty files under `lib/`, grouped by the layer that owns it,
|
|
31
|
+
and `testing/adding-a-verb.md` is the ordered walk a new command owes. It is
|
|
32
|
+
the gem's own documentation rather than a sample, so an installed okf now
|
|
33
|
+
carries a real bundle for a reader to open with the tool they just installed:
|
|
34
|
+
`okf server "$(gem contents okf --show-install-dir)/.okf"`.
|
|
35
|
+
|
|
36
|
+
It deliberately copies nothing from the repository's own bundle, which still
|
|
37
|
+
holds okf's format, model, capabilities and design constraints — a second copy
|
|
38
|
+
of a catalogue is worse than none.
|
|
39
|
+
|
|
40
|
+
`test/unit/bundle_catalog_test.rb` pins both halves: a file under `lib/` named
|
|
41
|
+
by no concept, a concept naming a file that is gone, or the repository
|
|
42
|
+
bundle's `cli.md` group table disagreeing with `OKF::CLI.builtins` all fail
|
|
43
|
+
the suite. That group table was code-derived and unchecked until now.
|
|
44
|
+
`test/unit/packaging_test.rb` pins that the bundle actually ships.
|
|
45
|
+
|
|
46
|
+
## [2.1.0] - 2026-08-17
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- **The skill's CLI reference is an index and seven leaves.** `reference/cli.md`
|
|
51
|
+
answered every question about every verb in one 46,234-byte file, so an agent
|
|
52
|
+
asking about `search` paid for `serve`, `registry` and the graph too. The
|
|
53
|
+
shared contract — refs, exit codes, `--json`, the filters — stays in `cli.md`
|
|
54
|
+
and routes to one file per surface under `reference/cli/`. Measured on the
|
|
55
|
+
worst question rather than the mean: 9,084 bytes for a routing question,
|
|
56
|
+
19,533 for the heaviest leaf. `reference/spec-map.md` is the other half, a
|
|
57
|
+
pointer from a spec clause to the file that answers it, so the vendored
|
|
58
|
+
`SPEC.md` keeps its index beside it instead of cut into it.
|
|
59
|
+
- **Cross-file citations in the skill name a `rule:` marker**, not a section
|
|
60
|
+
anchor: the key travels with the paragraph the next time anything moves.
|
|
61
|
+
- **`okf help` prints one row per extension**, plus a pointer to
|
|
62
|
+
`okf <verb> --help` for the rest. An addon with an umbrella verb and several
|
|
63
|
+
subcommands used to dwarf the built-ins the map exists to teach.
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
|
|
67
|
+
- **The skill teaches what a log records.** `log.md` carries durable knowledge
|
|
68
|
+
and shipped behavior, never the process that produced them —
|
|
69
|
+
`rule:okf-log-durable-only` in `reference/authoring.md`, cited by the maintain
|
|
70
|
+
playbook and the Closeout gate. It was the okf-gem repository's own contract
|
|
71
|
+
before this, which an agent maintaining any other bundle never reads.
|
|
72
|
+
|
|
8
73
|
## [2.0.0] - 2026-08-14
|
|
9
74
|
|
|
10
75
|
> Major, not minor. The Breaking entries below change public shapes a shipped
|
|
@@ -1410,7 +1475,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1410
1475
|
### Added
|
|
1411
1476
|
|
|
1412
1477
|
- Claude Code plugin. The repository now doubles as a plugin marketplace:
|
|
1413
|
-
`/plugin marketplace add serradura/okf
|
|
1478
|
+
`/plugin marketplace add serradura/okf`, then `/plugin install okf@okfgem`.
|
|
1414
1479
|
The plugin carries the canonical skill (a generated copy; `rake plugin:sync`
|
|
1415
1480
|
keeps it in lockstep with `lib/okf/skill`, and a test fails on drift), one
|
|
1416
1481
|
front-door command (`/okf:gem`: no arguments orients on the CLI, the bundle,
|
|
@@ -1516,18 +1581,20 @@ Initial release.
|
|
|
1516
1581
|
|
|
1517
1582
|
- Runs on Ruby >= 2.4 with two runtime dependencies: rack and webrick.
|
|
1518
1583
|
|
|
1519
|
-
[2.
|
|
1520
|
-
[1.
|
|
1521
|
-
[
|
|
1522
|
-
[1.
|
|
1523
|
-
[1.
|
|
1524
|
-
[1.
|
|
1525
|
-
[1.
|
|
1526
|
-
[1.
|
|
1527
|
-
[1.
|
|
1528
|
-
[1.
|
|
1529
|
-
[1.
|
|
1530
|
-
[1.
|
|
1531
|
-
[1.
|
|
1532
|
-
[1.
|
|
1533
|
-
[1.
|
|
1584
|
+
[2.1.1]: https://github.com/serradura/okf/compare/v2.1.0...v2.1.1
|
|
1585
|
+
[2.1.0]: https://github.com/serradura/okf/compare/v2.0.0...v2.1.0
|
|
1586
|
+
[2.0.0]: https://github.com/serradura/okf/compare/v1.13.0...v2.0.0
|
|
1587
|
+
[1.13.0]: https://github.com/serradura/okf/compare/v1.12.0...v1.13.0
|
|
1588
|
+
[1.12.0]: https://github.com/serradura/okf/compare/v1.11.0...v1.12.0
|
|
1589
|
+
[1.11.0]: https://github.com/serradura/okf/compare/v1.10.0...v1.11.0
|
|
1590
|
+
[1.10.0]: https://github.com/serradura/okf/compare/v1.9.0...v1.10.0
|
|
1591
|
+
[1.9.0]: https://github.com/serradura/okf/compare/v1.8.0...v1.9.0
|
|
1592
|
+
[1.8.0]: https://github.com/serradura/okf/compare/v1.7.0...v1.8.0
|
|
1593
|
+
[1.7.0]: https://github.com/serradura/okf/compare/v1.6.0...v1.7.0
|
|
1594
|
+
[1.6.0]: https://github.com/serradura/okf/compare/v1.5.0...v1.6.0
|
|
1595
|
+
[1.5.0]: https://github.com/serradura/okf/compare/v1.4.0...v1.5.0
|
|
1596
|
+
[1.4.0]: https://github.com/serradura/okf/compare/v1.3.0...v1.4.0
|
|
1597
|
+
[1.3.0]: https://github.com/serradura/okf/compare/v1.2.0...v1.3.0
|
|
1598
|
+
[1.2.0]: https://github.com/serradura/okf/compare/v1.1.0...v1.2.0
|
|
1599
|
+
[1.1.0]: https://github.com/serradura/okf/compare/v1.0.0...v1.1.0
|
|
1600
|
+
[1.0.0]: https://github.com/serradura/okf/releases/tag/v1.0.0
|
data/README.md
CHANGED
|
@@ -5,7 +5,7 @@ ranked search, and a live knowledge graph. 100% local.**
|
|
|
5
5
|
|
|
6
6
|
[Site](https://okfgem.com) · [Docs](https://okfgem.com/docs/) ·
|
|
7
7
|
[Live demo](https://demo.okfgem.com) ·
|
|
8
|
-
[Project README](https://github.com/serradura/okf
|
|
8
|
+
[Project README](https://github.com/serradura/okf#readme)
|
|
9
9
|
|
|
10
10
|
OKF (Open Knowledge Format) is portable project knowledge: Markdown files with
|
|
11
11
|
YAML frontmatter that both humans and agents read from one source. This gem is
|
|
@@ -22,20 +22,41 @@ on every Ruby since **2.4** — the one your OS already ships.
|
|
|
22
22
|
|
|
23
23
|
## Install
|
|
24
24
|
|
|
25
|
+
> **In Claude Code**, the plugin is the fastest path: two commands install the whole
|
|
26
|
+
> toolchain (skill, `/okf:gem`, and the curation hook). See the
|
|
27
|
+
> [project README](https://github.com/serradura/okf#claude-code-plugin).
|
|
28
|
+
> Everywhere else, install the gem:
|
|
29
|
+
|
|
25
30
|
```bash
|
|
26
31
|
gem install okf
|
|
27
32
|
# or, in a project
|
|
28
33
|
bundle add okf
|
|
29
34
|
```
|
|
30
35
|
|
|
31
|
-
|
|
36
|
+
Tested and supported on every Ruby from **2.4 through 4.0**. From a checkout,
|
|
37
|
+
`bundle exec rake install` builds and installs it locally.
|
|
38
|
+
|
|
39
|
+
## No Ruby? Use Docker
|
|
40
|
+
|
|
41
|
+
The official image bundles the CLI, so every `okf` command runs against a bundle
|
|
42
|
+
you mount at `/data`:
|
|
32
43
|
|
|
33
44
|
```bash
|
|
34
45
|
docker run --rm -v "$PWD:/data" ghcr.io/serradura/okf validate .
|
|
46
|
+
docker run --rm -v "$PWD:/data" -p 8808:8808 ghcr.io/serradura/okf server . --bind 0.0.0.0
|
|
35
47
|
```
|
|
36
48
|
|
|
37
|
-
The Docker-backed [`okf` command](https://docker.okfgem.com)
|
|
38
|
-
every verb reads exactly like the native CLI
|
|
49
|
+
Tired of the long line? The Docker-backed [`okf` command](https://docker.okfgem.com)
|
|
50
|
+
drops the prefix so every verb reads exactly like the native CLI:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
curl -fsSL https://docker.okfgem.com/install.sh | sh # PowerShell: irm https://docker.okfgem.com/install.ps1 | iex
|
|
54
|
+
okf validate .
|
|
55
|
+
okf server .
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Images are published for `linux/amd64` and `linux/arm64` on
|
|
59
|
+
[ghcr.io](https://github.com/serradura/okf/pkgs/container/okf).
|
|
39
60
|
|
|
40
61
|
## Four steps to your first bundle
|
|
41
62
|
|
|
@@ -55,6 +76,41 @@ okf server <folder> # 4. explore what you got, as a live graph
|
|
|
55
76
|
|
|
56
77
|
Then `/okf maintain` keeps it in sync as the code changes.
|
|
57
78
|
|
|
79
|
+
What the gem does, and which verb does it. This table is the map; **[the
|
|
80
|
+
docs](https://okfgem.com/docs/)** are the manual.
|
|
81
|
+
|
|
82
|
+
| Capability | What it answers | Verb |
|
|
83
|
+
| ------------------------------------------------------------- | --------------------------------- | -------------------------- |
|
|
84
|
+
| [Companion agent skill](https://okfgem.com/docs/skill/) | Can an agent author it? | `skill` |
|
|
85
|
+
| [Conformance validator](https://okfgem.com/docs/cli/validate/) | Is this a legal OKF bundle? | `validate` |
|
|
86
|
+
| [Curation linter](https://okfgem.com/docs/cli/lint/) | Is it navigable, complete, fresh? | `lint` / `loose` |
|
|
87
|
+
| [Ranked text search](https://okfgem.com/docs/cli/search/) | Which concept covers X? | `search` |
|
|
88
|
+
| [Read views](https://okfgem.com/docs/cli/) | What is in here, and where? | `index` / `dirs` / `catalog` |
|
|
89
|
+
| [Interactive graph server](https://okfgem.com/docs/cli/server/) | Can I explore it visually? | `server` |
|
|
90
|
+
| [Static render](https://okfgem.com/docs/cli/render/) | Can I ship a serverless snapshot? | `render` |
|
|
91
|
+
| [Library API](https://okfgem.com/docs/library/) | Can my Ruby program use it? | in-process |
|
|
92
|
+
|
|
93
|
+
And because knowledge rarely lives in one bundle, a registry gives each one a
|
|
94
|
+
name — see [one registry, many bundles](#one-registry-many-bundles) below.
|
|
95
|
+
|
|
96
|
+
## The graph
|
|
97
|
+
|
|
98
|
+
One page, from a phone to a desktop: the navigation rail becomes a drawer, the
|
|
99
|
+
toolbar folds into a `⚙` sheet, and a tap opens a preview card at the bottom edge
|
|
100
|
+
rather than a panel over the whole viewport, so the graph stays live while you
|
|
101
|
+
read. Drag the card up for the neighbourhood, tap a link and it walks there in
|
|
102
|
+
place.
|
|
103
|
+
|
|
104
|
+
It is keyboard-first: **`⌘/Ctrl-K`** opens a command palette that searches
|
|
105
|
+
concepts, jumps to a view, and — behind a [hub](#one-registry-many-bundles) —
|
|
106
|
+
switches bundles. **`/`** jumps to the current view's search, **`?`** answers with
|
|
107
|
+
every shortcut. Cluster mode boxes the graph by directory and nests as deep as
|
|
108
|
+
your tree does.
|
|
109
|
+
|
|
110
|
+
To skip the server entirely, **`okf render <dir>`** writes that same page as one
|
|
111
|
+
self-contained HTML file, the whole bundle baked in, so you can publish the graph
|
|
112
|
+
on GitHub Pages or any static host.
|
|
113
|
+
|
|
58
114
|
## The command line
|
|
59
115
|
|
|
60
116
|
Written to be read by an **agent first and a person second** — that is what the
|
|
@@ -83,16 +139,130 @@ Exit codes: `0` success, `1` non-conformant bundle (or a `lint --fail-on`
|
|
|
83
139
|
threshold crossed), `2` usage error. Every flag is in `okf <verb> --help` and in
|
|
84
140
|
[the docs](https://okfgem.com/docs/).
|
|
85
141
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
142
|
+
```bash
|
|
143
|
+
$ okf validate docs
|
|
144
|
+
OKF v0.2 conformance — docs
|
|
145
|
+
concepts: 37 index.md: 10 log.md: 1
|
|
146
|
+
! warn features/link-suggestions.md: cross-link target not found: `/graph-view.md` (tolerated under §6.1)
|
|
147
|
+
…
|
|
148
|
+
✓ conformant (33 warning(s))
|
|
149
|
+
|
|
150
|
+
$ okf server docs
|
|
151
|
+
serving 37 concepts at http://127.0.0.1:8808 (Ctrl-C to stop)
|
|
152
|
+
|
|
153
|
+
$ okf render docs > public/index.html # the same page, static — host it anywhere
|
|
154
|
+
```
|
|
91
155
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
156
|
+
## One registry, many bundles
|
|
157
|
+
|
|
158
|
+
The registry is a per-user, ordered list of bundles in one plain JSON file (`$OKF_HOME/registry.json`, default `~/.okf`) — hand-editable,
|
|
159
|
+
greppable, no database. It stores references, never content: the bundles stay in
|
|
160
|
+
the repos that own them.
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
okf registry set ./docs --as handbook # give the bundle a name
|
|
164
|
+
okf lint @handbook # @slug works wherever a <dir> does, from anywhere
|
|
165
|
+
okf search @all rate limit # ranked retrieval across every registered bundle
|
|
166
|
+
okf server # no args: the whole registry behind one hub
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Related bundles can share a name: `okf registry group backend @handbook @runbooks`
|
|
170
|
+
makes `@backend` stand for the set (members can be groups too, so they nest), and
|
|
171
|
+
`okf search @backend rate limit` or `okf server @backend` then targets all of them
|
|
172
|
+
at once — a durable subset for the two verbs that take several bundles.
|
|
173
|
+
|
|
174
|
+
The registry lives under `$OKF_HOME` (default `~/.okf`) — one per user. For one
|
|
175
|
+
scoped to a single project instead, `okf registry init` drops a
|
|
176
|
+
`.okf-registry.json` in the current directory; okf then discovers it by walking up
|
|
177
|
+
from wherever you run, and every registry op — and every `@slug` — resolves through
|
|
178
|
+
it in place of the global one. So a bare `okf server` inside that repo serves *its*
|
|
179
|
+
bundles with no `$OKF_HOME` setup. The nearest registry wins, and
|
|
180
|
+
`OKF_NO_DISCOVERY=1` forces the global one.
|
|
181
|
+
|
|
182
|
+
Commit that file and it travels with the repo: a bundle under the project root is
|
|
183
|
+
stored relative to the registry, so a checkout on another machine — or a container
|
|
184
|
+
that mounts the repo — resolves the same bundles unchanged. (Bundles outside the
|
|
185
|
+
tree keep absolute paths, which do not travel.)
|
|
186
|
+
|
|
187
|
+
Behind the hub each bundle mounts at `/b/<slug>/`, `/b/` lists them all, and the
|
|
188
|
+
`⌘/Ctrl-K` palette both switches bundles and **searches every one at once** — type
|
|
189
|
+
a few words and the matching concepts appear with their bundle and a snippet, from
|
|
190
|
+
wherever you are.
|
|
191
|
+
|
|
192
|
+
The ⚙ rail opens **Bundles**, the registry on the graph page itself: make
|
|
193
|
+
default, rename, remove, where you are already reading. Those controls are the one
|
|
194
|
+
thing that does not follow you onto a network — bind anywhere but loopback and
|
|
195
|
+
they are refused outright, since `--bind 0.0.0.0` is how a personal tool becomes a
|
|
196
|
+
public one.
|
|
197
|
+
|
|
198
|
+
## Reading a big bundle a level at a time
|
|
199
|
+
|
|
200
|
+
A few hundred concepts is a map nobody reads whole, so `index` and `dirs` descend
|
|
201
|
+
instead of dumping. `--dir` takes a directory **and everything under it**,
|
|
202
|
+
`--depth N` bounds how far below that it goes, and the two compose the way you
|
|
203
|
+
actually walk a tree:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
okf dirs @handbook # the shape: every dir, what it holds directly and below
|
|
207
|
+
okf index @handbook --depth 1 --no-body # the top of the map, no prose
|
|
208
|
+
okf index @handbook --dir platform/api # now open one branch — with the chain that places it
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Naming a `--dir` brings its ancestors along, marked `↑`, so a branch is never
|
|
212
|
+
shown adrift of the context that says what it is — the root `index.md`'s prose
|
|
213
|
+
first among it.
|
|
214
|
+
|
|
215
|
+
For an agent the saving is the whole point. On a 400-concept bundle the full
|
|
216
|
+
`okf index --json` is 313 KB; the skeleton it orients on is 2.8 KB:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
okf index @handbook --json --depth 1 --except body,listing
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## The agent skill
|
|
223
|
+
|
|
224
|
+
The gem carries the [companion OKF agent skill](https://okfgem.com/docs/skill/):
|
|
225
|
+
a `SKILL.md` plus reference and template files that teach a coding agent to
|
|
226
|
+
author, maintain, and consume OKF bundles and to drive
|
|
227
|
+
[the command line](#the-command-line).
|
|
228
|
+
Because the skill ships inside the gem, installing the gem already puts the skill
|
|
229
|
+
on your machine, and the skill's CLI reference can never drift from the
|
|
230
|
+
executable it was released with.
|
|
231
|
+
|
|
232
|
+
The skill routes a small set of verbs. In Claude Code they run as `/okf:gem
|
|
233
|
+
<verb>`; used standalone, the skill infers the verb from your request.
|
|
234
|
+
|
|
235
|
+
| Verb | What it does |
|
|
236
|
+
| ---------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
237
|
+
| _(none)_ | Orient on the bundle and recommend the highest-value next move |
|
|
238
|
+
| `search` | Answer a question from the bundle, token-lean: the map, the finder, only the winning bodies |
|
|
239
|
+
| `produce` | Create or extend a bundle from code, docs, or knowledge in people's heads |
|
|
240
|
+
| `migrate` | Adopt existing Markdown docs in place: frontmatter and reserved files added, bodies kept verbatim |
|
|
241
|
+
| `maintain` | Sync the bundle's content with reality after the code or docs change |
|
|
242
|
+
| `refine` | Restructure it for retrieval: evidence-first, cohesion over balance — proposes, never applies |
|
|
243
|
+
| `consume` | Use the bundle as context for a task, writing back what you learn |
|
|
244
|
+
| `curate` | Structural upkeep as it stands: `validate` + `lint` + `loose` |
|
|
245
|
+
| `doctor` | Install and verify the CLI, then doctor the bundle |
|
|
246
|
+
| `<okf-cli-verb>` | Run any CLI verb (`validate`, `lint`, `search`, `index`, `server`, the read views) and interpret its output |
|
|
247
|
+
|
|
248
|
+
Three of those look alike and are not, which is the distinction worth learning
|
|
249
|
+
first: **`curate`** keeps the bundle *sound* (the structure as it stands),
|
|
250
|
+
**`maintain`** keeps it *true* (the code changed, so the content must catch up),
|
|
251
|
+
and **`refine`** changes *where knowledge lives* — the folder a concept sits in,
|
|
252
|
+
a fact re-explained in three overviews. Reach for `refine` when nothing is wrong
|
|
253
|
+
and everything is hard to find. It reads the evidence, then hands you a proposal
|
|
254
|
+
— it never rearranges your bundle on its own.
|
|
255
|
+
|
|
256
|
+
Point it at your agent's config directory and the tree settles in its own
|
|
257
|
+
`skills/okf/` folder, so a shared skills directory never gets the files loose:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
okf skill .claude # Claude Code -> .claude/skills/okf
|
|
261
|
+
okf skill .agents # agent-agnostic -> .agents/skills/okf
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The resolved directory must be empty unless you pass `--force`, so a customized
|
|
265
|
+
skill is never clobbered.
|
|
96
266
|
|
|
97
267
|
## The library
|
|
98
268
|
|
|
@@ -158,9 +328,12 @@ without ever failing it.
|
|
|
158
328
|
Publish a gem named `okf-*` carrying an `okf/plugin.rb` and installing it is the
|
|
159
329
|
whole installation: your verb answers to `okf` and behaves like a built-in.
|
|
160
330
|
Nothing an addon registers can displace one, and a broken addon is skipped rather
|
|
161
|
-
than taking the CLI down.
|
|
162
|
-
|
|
163
|
-
|
|
331
|
+
than taking the CLI down. Three ship alongside this one, with nothing in this
|
|
332
|
+
gem naming any of them: [`okf-mcp`](https://rubygems.org/gems/okf-mcp) serves
|
|
333
|
+
your bundles over the Model Context Protocol,
|
|
334
|
+
[`okf-tui`](https://rubygems.org/gems/okf-tui) browses them full-screen in a
|
|
335
|
+
terminal, and [`okf-pro`](https://rubygems.org/gems/okf-pro) writes an
|
|
336
|
+
agent's knowledge repository and enforces it at three doors.
|
|
164
337
|
|
|
165
338
|
The graph page treats a bundle as untrusted content: inlined data is escaped and
|
|
166
339
|
every concept body is sanitized before it reaches the DOM, so a script hidden in
|
|
@@ -170,11 +343,22 @@ do not know.
|
|
|
170
343
|
|
|
171
344
|
## More
|
|
172
345
|
|
|
173
|
-
The [project README](https://github.com/serradura/okf
|
|
174
|
-
diagrams, the comparison with `CLAUDE.md`, agent auto-memory and wikis,
|
|
175
|
-
Claude Code plugin
|
|
176
|
-
|
|
177
|
-
|
|
346
|
+
The [project README](https://github.com/serradura/okf#readme) carries the
|
|
347
|
+
diagrams, the comparison with `CLAUDE.md`, agent auto-memory and wikis, the
|
|
348
|
+
Claude Code plugin, and the way to install the skill into any agent without this
|
|
349
|
+
gem (`npx skills add serradura/okf`). The [docs](https://okfgem.com/docs/) are the manual.
|
|
350
|
+
|
|
351
|
+
And the gem documents *itself* in OKF. `.okf/` ships inside it — a map of what
|
|
352
|
+
every file under `lib/` does, and the walk a new verb owes — so from an
|
|
353
|
+
installed copy:
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
okf server "$(gem contents okf --show-install-dir)/.okf"
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
reads this gem's own knowledge as a graph, in this gem. That is the shortest
|
|
360
|
+
honest demonstration there is: the format is good enough that the tool's
|
|
361
|
+
maintainers use it on the tool.
|
|
178
362
|
|
|
179
363
|
## License
|
|
180
364
|
|
data/lib/okf/cli.rb
CHANGED
|
@@ -92,7 +92,7 @@ module OKF
|
|
|
92
92
|
[ :judge, nil ],
|
|
93
93
|
[ :read, nil ],
|
|
94
94
|
[ :graph, nil ],
|
|
95
|
-
[ :extension, " installed extensions:" ]
|
|
95
|
+
[ :extension, " installed extensions (`okf <verb> --help` for each):" ]
|
|
96
96
|
].freeze
|
|
97
97
|
|
|
98
98
|
# Everything the map's grammar column cannot say for itself. A test finds the
|
|
@@ -476,13 +476,31 @@ module OKF
|
|
|
476
476
|
end
|
|
477
477
|
|
|
478
478
|
def print_group(io, group, heading)
|
|
479
|
-
|
|
479
|
+
commands = self.class.commands.reject(&:hidden?).select { |command| command.group == group }
|
|
480
|
+
rows = group == :extension ? extension_rows(commands) : commands.flat_map(&:help_rows)
|
|
480
481
|
return if rows.empty?
|
|
481
482
|
|
|
482
483
|
io.puts heading if heading
|
|
483
484
|
rows.each { |left, desc| io.puts " #{left.to_s.ljust(56)}#{desc}" }
|
|
484
485
|
io.puts
|
|
485
486
|
end
|
|
487
|
+
|
|
488
|
+
# One line per extension, whatever it declares — its FIRST row, which is why
|
|
489
|
+
# an addon's first row should be its summary.
|
|
490
|
+
#
|
|
491
|
+
# Enforced here rather than asked of each addon, because a rule an addon has
|
|
492
|
+
# to remember is a rule this map cannot rely on. An umbrella verb is a shape
|
|
493
|
+
# an addon legitimately has — the built-in `registry` has it too — and one
|
|
494
|
+
# arriving with eight subcommands made this block the longest section on the
|
|
495
|
+
# page, dwarfing the built-ins above it and burying the single-line addons
|
|
496
|
+
# beside it.
|
|
497
|
+
#
|
|
498
|
+
# A built-in keeps every row: those are this gem's own surface, they are what
|
|
499
|
+
# the map exists to teach, and there is no second place to read them. An
|
|
500
|
+
# extension has one — `okf <verb> --help`, which the heading points at.
|
|
501
|
+
def extension_rows(commands)
|
|
502
|
+
commands.map { |command| command.help_rows.first }.compact
|
|
503
|
+
end
|
|
486
504
|
end
|
|
487
505
|
end
|
|
488
506
|
|
data/lib/okf/skill/SKILL.md
CHANGED
|
@@ -96,11 +96,18 @@ The one trap worth carrying in your head: **the age cutoff is off by default**
|
|
|
96
96
|
a plain `okf lint` reports concepts past their own declared `stale_after` (the
|
|
97
97
|
`expired` check reads the clock the CLI supplies), but never judges *age*; pass
|
|
98
98
|
`--stale-after <90d|12w|ISO-date>` when you want anything not touched since then
|
|
99
|
-
flagged too
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
flagged too — the two mechanisms share a spelling and nothing else
|
|
100
|
+
([cli/checks.md](reference/cli/checks.md), rule `okf-two-clocks`).
|
|
101
|
+
<!-- check:stale -->
|
|
102
|
+
|
|
103
|
+
Read [cli.md](reference/cli.md) before *interpreting* a verb's output in depth.
|
|
104
|
+
It is the index and the shared contract — refs, exit codes, `--json`, the
|
|
105
|
+
filters — and its table routes to the one file the verb lives in:
|
|
106
|
+
[checks](reference/cli/checks.md) (what `validate` may and may not reject, lint's
|
|
107
|
+
categories and check ids), [search](reference/cli/search.md),
|
|
108
|
+
[map](reference/cli/map.md) (`index`/`dirs`), [views](reference/cli/views.md)
|
|
109
|
+
(the tag-curation views), [serve](reference/cli/serve.md) (the trust boundary),
|
|
110
|
+
[registry](reference/cli/registry.md), [graph](reference/cli/graph.md).
|
|
104
111
|
|
|
105
112
|
## Orient before you touch anything
|
|
106
113
|
|
|
@@ -123,8 +130,9 @@ playbooks (the Commands table below; no `okf` installed? read the root
|
|
|
123
130
|
`consume` (use it as context) carry the judgment the executable can't — this is
|
|
124
131
|
where the skill earns its keep. Each has a playbook (the Commands table below);
|
|
125
132
|
read the modelling craft in [authoring.md](reference/authoring.md) before
|
|
126
|
-
producing or maintaining
|
|
127
|
-
|
|
133
|
+
producing or maintaining. When you need chapter and verse, go through
|
|
134
|
+
[spec-map.md](reference/spec-map.md) — which § settles which question — into the
|
|
135
|
+
verbatim [SPEC.md](reference/SPEC.md).
|
|
128
136
|
|
|
129
137
|
**No subcommand?** Infer intent: "document this / capture X" → `produce`;
|
|
130
138
|
"convert / migrate / OKFy these existing docs into a bundle" → `migrate`; "the
|
|
@@ -25,7 +25,9 @@ lives in [authoring.md](../reference/authoring.md).
|
|
|
25
25
|
silently deleting the context that explains them.
|
|
26
26
|
4. **Update every enumeration that names what you changed — including `index.md`
|
|
27
27
|
bodies**, not just the concept files: a new, renamed, or removed concept changes
|
|
28
|
-
its directory's index listing too. Append a dated `log.md` entry
|
|
28
|
+
its directory's index listing too. Append a dated `log.md` entry — what changed and why it
|
|
29
|
+
matters, never the rounds it took (rule `okf-log-durable-only` in
|
|
30
|
+
[authoring.md](../reference/authoring.md)). Step 1's map
|
|
29
31
|
is how you verify this — re-run `okf index` and confirm each listing matches
|
|
30
32
|
reality.
|
|
31
33
|
5. Run `validate`, then `lint` to catch the curation drift the change introduced —
|
|
@@ -4,7 +4,8 @@ The craft that makes these steps land well — granularity, choosing `type`, tag
|
|
|
4
4
|
vocabulary, topology, links, sources — lives in
|
|
5
5
|
[authoring.md](../reference/authoring.md). Read it before a non-trivial produce.
|
|
6
6
|
|
|
7
|
-
1.
|
|
7
|
+
1. Unsure of a rule? [spec-map.md](../reference/spec-map.md) names the § that
|
|
8
|
+
settles it; read that section of [SPEC.md](../reference/SPEC.md).
|
|
8
9
|
2. Pick the source(s): **code** (derive concepts from source, READMEs, docstrings,
|
|
9
10
|
config), **docs/wiki** (distill pages into concepts; record the originals in
|
|
10
11
|
`sources:` and key claims with `[^id]` footnotes), **manual** (decisions,
|
|
@@ -27,5 +28,6 @@ vocabulary, topology, links, sources — lives in
|
|
|
27
28
|
`okf_version: "0.2"`. Append a dated entry to `log.md`.
|
|
28
29
|
6. **Close out** — walk the
|
|
29
30
|
[Closeout gate](../reference/authoring.md#closeout--the-finishing-gate)
|
|
30
|
-
(`validate` + `lint` are part of it, see
|
|
31
|
+
(`validate` + `lint` are part of it, see
|
|
32
|
+
[cli/checks.md](../reference/cli/checks.md))
|
|
31
33
|
before finishing.
|
|
@@ -1,33 +1,13 @@
|
|
|
1
1
|
# Authoring OKF well — the craft
|
|
2
2
|
|
|
3
|
-
The spec ([SPEC.md](SPEC.md)) tells you what is *legal
|
|
4
|
-
|
|
3
|
+
The spec ([SPEC.md](SPEC.md)) tells you what is *legal*, and
|
|
4
|
+
[spec-map.md](spec-map.md) says which § settles which question. This file is
|
|
5
|
+
what is *good* — the modelling judgment that turns a pile of conformant files into
|
|
5
6
|
knowledge worth consuming. Read it before `produce` or `maintain`, and keep the
|
|
6
7
|
§11 conformance rules in mind (parseable frontmatter, a non-empty `type`, and
|
|
7
8
|
well-formed reserved files — the hard rules in [SKILL.md](../SKILL.md));
|
|
8
9
|
everything else is guidance a consumer must tolerate.
|
|
9
10
|
|
|
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.1 | provenance — `sources` and its credibility signals | any external or empirical claim |
|
|
19
|
-
| §5.2 / §5.3 | trust — `generated`, `verified`, and the derived tiers | recording who wrote or confirmed content |
|
|
20
|
-
| §5.4 / §5.5 | lifecycle — `status`, `stale_after` | marking drafts, deprecations, expiries |
|
|
21
|
-
| §6 / §6.1 | cross-links; **broken links are tolerated** | linking; judging a "broken" link |
|
|
22
|
-
| §6.2 / §6.3 | path-valued fields; the `references/` convention | pointing at non-concept assets |
|
|
23
|
-
| §7 | the actor convention | filling any `by` |
|
|
24
|
-
| §8 | index files & progressive disclosure | orienting; writing or synthesizing an index |
|
|
25
|
-
| §9 | log files | recording history |
|
|
26
|
-
| §10 | attested computations | a concept that *is* a sanctioned computation |
|
|
27
|
-
| §11 | conformance — the hard gate | what `validate` may and may not reject |
|
|
28
|
-
| §12 | versioning (`okf_version`) | the root index's one allowed field |
|
|
29
|
-
| §13 | changes from v0.1 | migrating a bundle; reading an unmigrated one |
|
|
30
|
-
|
|
31
11
|
## Modelling principles
|
|
32
12
|
|
|
33
13
|
These are the decisions that make or break a bundle. None are enforced by the
|
|
@@ -177,7 +157,8 @@ declare it only when it says something. `stale_after` is an absolute
|
|
|
177
157
|
the day itself. Use it for knowledge with a known shelf life (a quota, a
|
|
178
158
|
migration window); `lint`'s `expired` check reports the ones whose date has
|
|
179
159
|
passed. It is a declared expiry, distinct from the `--stale-after` *flag*,
|
|
180
|
-
which is a reader-supplied age cutoff — see [cli.md](cli.md)
|
|
160
|
+
which is a reader-supplied age cutoff — see [cli/checks.md](cli/checks.md),
|
|
161
|
+
rule `okf-two-clocks`.
|
|
181
162
|
|
|
182
163
|
### Capture the non-obvious — not what code already says <!-- rule:okf-non-obvious -->
|
|
183
164
|
A bundle that restates function signatures or config keys goes stale the moment
|
|
@@ -217,6 +198,21 @@ concepts. Templates: [concept](../templates/concept.md),
|
|
|
217
198
|
nested [index](../templates/index.md), bundle-root
|
|
218
199
|
[root-index](../templates/root-index.md), [log](../templates/log.md).
|
|
219
200
|
|
|
201
|
+
### The log records what shipped, not how it shipped <!-- rule:okf-log-durable-only -->
|
|
202
|
+
`log.md` carries durable knowledge and shipped behavior — never the process that
|
|
203
|
+
produced them. A bug fixed in a release is an entry; the review rounds that found
|
|
204
|
+
it are not. A capability that shipped is an entry; the iterations it took to
|
|
205
|
+
stabilize it before it shipped are not. When a change taught a lesson, the lesson
|
|
206
|
+
belongs in the concept it is about, stated as a principle, and the log entry
|
|
207
|
+
*points* at that concept instead of re-narrating the rounds — a reader finds it
|
|
208
|
+
where the subject lives, not by reading history.
|
|
209
|
+
|
|
210
|
+
The bar is what a reader six months out needs: *what changed and why it matters*,
|
|
211
|
+
never *how many passes it took to get there*. Watch for the shape this invites —
|
|
212
|
+
the newest entries sit at the top where every reader lands, so a stretch of work
|
|
213
|
+
stabilized by iteration accretes "round N found M defects" exactly where a durable
|
|
214
|
+
summary belongs.
|
|
215
|
+
|
|
220
216
|
## Migrating from v0.1 (§13)
|
|
221
217
|
|
|
222
218
|
A v0.1 bundle is consumable forever — §13.1 sanctions reading `timestamp` as
|
|
@@ -237,7 +233,7 @@ verb (search, produce, migrate, maintain, consume, curate, doctor), routed by th
|
|
|
237
233
|
Commands table in [SKILL.md](../SKILL.md). The Closeout below is their shared
|
|
238
234
|
finishing gate.
|
|
239
235
|
|
|
240
|
-
## Closeout — the finishing gate
|
|
236
|
+
## Closeout — the finishing gate <!-- rule:okf-closeout-gate -->
|
|
241
237
|
|
|
242
238
|
`produce` step 6 and `maintain` steps 4–7 both land here: before calling an
|
|
243
239
|
authoring task done, walk this once. It is the repo's "turn every task into a check
|
|
@@ -247,7 +243,8 @@ grep can't:
|
|
|
247
243
|
- **Index enumerations** — every `index.md` that lists what you added, renamed, or
|
|
248
244
|
removed is updated; re-run `okf index` and eyeball each listing against reality.
|
|
249
245
|
Easy to skip, expensive to miss — this is the check that was missing.
|
|
250
|
-
- **`log.md`** — a dated entry, newest first
|
|
246
|
+
- **`log.md`** — a dated entry, newest first, and durable only (rule
|
|
247
|
+
`okf-log-durable-only` above).
|
|
251
248
|
- **`generated.at`** bumped on the concepts you touched (and `generated.by` says
|
|
252
249
|
who touched them — you, in §7's spelling).
|
|
253
250
|
- **`validate`** — zero §11 errors.
|