okf 1.6.0 → 1.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45d6619cf9144fbaf4026e51ad238213e916c6796ffd1199d189d6b64c47352e
4
- data.tar.gz: c26b86f1b2173feefd02159a2dd280f93a4e8ee915eb077ef49558fced6c8ac3
3
+ metadata.gz: 64b163bdb5b0e234c879f6d5424279b8b329a797292b6322af0379741e06565c
4
+ data.tar.gz: 816d6456345e3cd6e507be229b757f8143987ba2c98ffb1bcc26d45c19bdfba2
5
5
  SHA512:
6
- metadata.gz: 254038bdb6383fe94882793c6b2d2433917536793670d23fad1be4c2678e9a8c042164c997ba8ae64950ced447ca850e4263bb1eee9ab2230b33b2b83f8efd94
7
- data.tar.gz: 1ada5ef52a4848d340619a1ccf10bc35ddbae7504c3e53cc447f824e44f90d145579a024ae17c15c38eb84cc0592353b20967adda709c631a38a298161e6f99f
6
+ metadata.gz: 9ee06f232154bf609ce24882447de92f26e8a33ebddd593ff462bb83ad993d4f79c797a0c88f7647cbea9bba05b190a0b1da127e01e53d99a9b5e99d952eb76b
7
+ data.tar.gz: 69a26c944a1a393f7bcb58cdfd554ed1991c0617fe3fe9d7e138af7dd9847763df947d393a9cea1ff99182430b5f79b488bde78a79f0915740beab088501c4bd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.7.0] - 2026-07-16
4
+
5
+ - `okf server`: responses are gzipped when the client accepts it
6
+ (`Rack::Deflater` at the boot seam). Lossless and transparent — the browser
7
+ decompresses automatically — and no new dependency, since `Rack::Deflater`
8
+ ships inside rack. Clients that send no `Accept-Encoding` keep getting
9
+ identity responses. `okf render`'s static HTML is untouched.
10
+ - The agent skill gains a `migrate` verb (`playbooks/migrate.md`): convert
11
+ existing documentation into a conformant bundle **in place** — frontmatter
12
+ and reserved files added, bodies kept verbatim (`produce` keeps
13
+ distillation). The verb is routed from SKILL.md's Commands table and intent
14
+ inference, the menu playbook now leads with it when a target already holds
15
+ markdown docs, and pointing any verb at a directory that is not a bundle now
16
+ suggests `migrate` instead of grinding through the validate errors.
17
+ - The graph page's link-preview image points at the renamed
18
+ `okfgem.com/og-demo-v3.png`. The site's OG art was refreshed to drop "Live
19
+ Graph" from the package formula (it is `Agent Skill + CLI/Lib + Graph` now
20
+ that `okf render` makes the graph live *or* static), and the filename carries
21
+ the version so social scrapers pick the new art up.
22
+ - The plugin's `/okf:gem` command is now a pass-through shim: it hands its
23
+ arguments to the okf skill unchanged, making `SKILL.md` the single router
24
+ for every channel. The routing prose the command used to duplicate had no
25
+ drift guard (the sync test covers only the generated skill copy), and the
26
+ not-a-bundle `migrate` suggestion now lives in `SKILL.md`, so standalone
27
+ skill installs get it too.
28
+
3
29
  ## [1.6.0] - 2026-07-15
4
30
 
5
31
  - New CLI verb: `okf render <dir> [-o FILE]` — the live graph as one static,
data/README.md CHANGED
@@ -73,6 +73,44 @@ It is deliberately light so it runs on the Ruby your OS already ships:
73
73
  That range is not aspirational: CI runs the full test suite and RuboCop on every
74
74
  one of these on each push.
75
75
 
76
+ ## Try it in four steps
77
+
78
+ From zero to your first bundle.
79
+
80
+ **1. Get the `okf` command.** Two ways in; either one puts `okf` on your `PATH`.
81
+
82
+ ```bash
83
+ gem install okf # with Ruby
84
+ curl -fsSL https://docker.okfgem.com/install.sh | sh # no Ruby? Docker
85
+ ```
86
+
87
+ **2. Install the skill.** Teach your agent the format — Claude Code, or any
88
+ other agent.
89
+
90
+ ```bash
91
+ okf skill .claude # or: okf skill .agents
92
+ ```
93
+
94
+ **3. Start an agent session** where your project lives.
95
+
96
+ ```bash
97
+ claude
98
+ ```
99
+
100
+ **4. Make your first bundle.** Two ways in, by what you already have: docs keep
101
+ every word, code gets written up for you.
102
+
103
+ ```
104
+ /okf migrate <path-to-your-docs> # have docs? adopted in place, bodies verbatim
105
+ /okf produce based on <path-to-your-code> # only code? the skill authors the concepts
106
+ ```
107
+
108
+ > [!TIP]
109
+ > **Once you have a bundle**, run `/okf maintain` in the agent session to keep it
110
+ > in sync as the code changes, and `okf server <folder>` to explore it as a graph.
111
+ > In Claude Code, the [plugin](#claude-code-plugin) adds a post-edit curation hook
112
+ > that runs `validate` + `lint` for you.
113
+
76
114
  ## Why OKF
77
115
 
78
116
  Project knowledge (why a service exists, what a metric really measures, the
@@ -297,6 +335,7 @@ The skill routes a small set of verbs. In Claude Code they run as `/okf:gem
297
335
  | _(none)_ | Orient on the bundle and recommend the highest-value next move |
298
336
  | `search` | Answer a question from the bundle, token-lean: the map, the finder, only the winning bodies |
299
337
  | `produce` | Create or extend a bundle from code, docs, or knowledge in people's heads |
338
+ | `migrate` | Adopt existing Markdown docs in place: frontmatter and reserved files added, bodies kept verbatim |
300
339
  | `maintain` | Sync the bundle's content with reality after the code or docs change |
301
340
  | `consume` | Use the bundle as context for a task, writing back what you learn |
302
341
  | `curate` | Structural upkeep as it stands: `validate` + `lint` + `loose` |
@@ -455,7 +494,7 @@ The plugin carries three pieces:
455
494
  | Piece | What it does |
456
495
  | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
457
496
  | `okf` skill | The [companion skill](#agent-skill) above, bundled with the plugin (a generated copy that `rake plugin:sync` keeps identical to `lib/okf/skill`). |
458
- | `/okf:gem` | The front door, routed by argument. No arguments: orients on the CLI, the bundle, and what `validate`/`lint` report, then recommends the highest-value next move (never auto-runs). `doctor`: installs and verifies the `okf` CLI, then doctors the repo's bundle. `curate`: the full curation cycle (`validate` + `lint` + `loose`). Anything else (`produce`, `maintain`, `consume`, a CLI verb): handed to the skill. |
497
+ | `/okf:gem` | The front door: a pass-through that hands its arguments to the skill unchanged, so the [verb table](#agent-skill) above is the whole routing story `doctor` installs and verifies the CLI, `curate` runs the full cycle (`validate` + `lint` + `loose`), `produce`/`migrate`/`maintain`/`consume` and any CLI verb do what they say. No arguments: orients on the CLI, the bundle, and what `validate`/`lint` report, then recommends the highest-value next move (never auto-runs). |
459
498
  | Curation hook | After every Write or Edit inside a bundle, runs `okf validate` + `okf lint` and returns the findings as context. The checks are the CLI's own, so the feedback is deterministic. |
460
499
 
461
500
  The hook stays silent outside bundles, and when the CLI is missing it suggests
data/lib/okf/cli.rb CHANGED
@@ -194,6 +194,7 @@ module OKF
194
194
 
195
195
  def server(argv)
196
196
  require "okf/server/app"
197
+ require "rack/deflater"
197
198
 
198
199
  options = { port: 8808, bind: "127.0.0.1", title: nil, link: nil, layout: "cose" }
199
200
  parser = OptionParser.new do |o|
@@ -216,6 +217,7 @@ module OKF
216
217
  # tests drive this without a socket).
217
218
  def run_server(folder, options)
218
219
  app = OKF::Server::App.new(folder, title: options[:title] || folder.name, link: options[:link], layout: options[:layout])
220
+ app = Rack::Deflater.new(app) # gzip responses when the client accepts it — transparent, no new dependency
219
221
  @out.puts "serving #{folder.graph.nodes.size} concepts at http://#{options[:bind]}:#{options[:port]} (Ctrl-C to stop)"
220
222
  @runner.call(app, options[:bind], options[:port])
221
223
  end
@@ -8,7 +8,7 @@
8
8
  <meta property="og:site_name" content="OKF">
9
9
  <meta property="og:title" content="<%= og_title %>">
10
10
  <meta property="og:description" content="<%= og_desc %>">
11
- <meta property="og:image" content="https://okfgem.com/og-demo-v2.png">
11
+ <meta property="og:image" content="https://okfgem.com/og-demo-v3.png">
12
12
  <meta property="og:image:type" content="image/png">
13
13
  <meta property="og:image:width" content="1200">
14
14
  <meta property="og:image:height" content="630">
@@ -16,7 +16,7 @@
16
16
  <meta name="twitter:card" content="summary_large_image">
17
17
  <meta name="twitter:title" content="<%= og_title %>">
18
18
  <meta name="twitter:description" content="<%= og_desc %>">
19
- <meta name="twitter:image" content="https://okfgem.com/og-demo-v2.png">
19
+ <meta name="twitter:image" content="https://okfgem.com/og-demo-v3.png">
20
20
  <meta name="twitter:image:alt" content="An interactive Open Knowledge Format knowledge graph.">
21
21
  <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='24' fill='%231a1a1a'/><polygon points='38,44 62,44 50,82' fill='%237a0a1e'/><polygon points='18,44 38,44 50,82' fill='%23a8112c'/><polygon points='62,44 82,44 50,82' fill='%23a8112c'/><polygon points='35,28 18,44 38,44' fill='%23dc1e3c'/><polygon points='65,28 82,44 62,44' fill='%23dc1e3c'/><polygon points='35,28 65,28 62,44 38,44' fill='%23f43f5e'/><polygon points='36,29 49,29 42,42' fill='%23fff' opacity='.38'/><polygon points='35,28 65,28 82,44 50,82 18,44' fill='none' stroke='%23ff6b7f' stroke-width='2' stroke-linejoin='round'/></svg>">
22
22
  <script>/* Resolve theme before first paint so there is no flash. */
@@ -116,7 +116,8 @@ read the modelling craft in [authoring.md](reference/authoring.md) before
116
116
  producing or maintaining, and the verbatim spec [SPEC.md](reference/SPEC.md)
117
117
  when you need chapter and verse.
118
118
 
119
- **No subcommand?** Infer intent: "document this / capture X" → `produce`; "the
119
+ **No subcommand?** Infer intent: "document this / capture X" → `produce`;
120
+ "convert / migrate / OKFy these existing docs into a bundle" → `migrate`; "the
120
121
  code changed, update the docs" → `maintain`; "what do we know about X / where
121
122
  is X documented" → `search`; a repo already carrying a bundle plus a task
122
123
  needing its knowledge → `consume`; "check / graph / preview it" → run the
@@ -126,6 +127,11 @@ matching CLI verb and interpret the result. When genuinely ambiguous, ask.
126
127
  root, but first detect whether the project already keeps its bundle elsewhere
127
128
  (e.g. `docs/`) and prefer that. Commit the bundle alongside the code it describes.
128
129
 
130
+ **Target isn't a bundle?** When a verb points at a directory that holds markdown
131
+ but no root `index.md` carrying `okf_version` — `validate` failing wholesale on
132
+ missing frontmatter — don't grind through the errors: suggest `migrate` (OKFy it
133
+ in place, bodies verbatim) and let the user pick.
134
+
129
135
  ## Commands
130
136
 
131
137
  The first word of the arguments picks a row. **No arguments at all** — someone
@@ -139,6 +145,7 @@ Read the referenced playbook before executing — it *is* the procedure.
139
145
  | *(none)* | Orient | recommend the highest-value next move; never auto-run | [playbooks/menu.md](playbooks/menu.md) |
140
146
  | `search` | Use | answer a question from the bundle: map → finder → only the winning bodies | [playbooks/search.md](playbooks/search.md) |
141
147
  | `produce` | Author | create or extend a bundle | [playbooks/produce.md](playbooks/produce.md) |
148
+ | `migrate` | Author | convert existing docs in place: frontmatter + reserved files, bodies verbatim | [playbooks/migrate.md](playbooks/migrate.md) |
142
149
  | `maintain` | Author | sync the bundle's content with reality after a change | [playbooks/maintain.md](playbooks/maintain.md) |
143
150
  | `consume` | Use | use the bundle as context for a task | [playbooks/consume.md](playbooks/consume.md) |
144
151
  | `curate` | Curate | structural upkeep as it stands: validate + lint + loose | [playbooks/curate.md](playbooks/curate.md) |
@@ -11,8 +11,11 @@ is the lede.
11
11
  here. Everything below needs the CLI.
12
12
  2. **Bundle present?** Locate one: the directory you were given, else a `.okf/`
13
13
  directory or a root `index.md` whose frontmatter carries `okf_version`.
14
- - **No bundle** → lead with **`produce`** (create the first bundle from the
15
- code, docs, or what lives only in people's heads). Nothing else applies yet.
14
+ - **No bundle** → when the target (or an obvious docs directory) already
15
+ holds markdown documentation, lead with **`migrate`** (OKFy it in place
16
+ frontmatter on, bodies verbatim); otherwise lead with **`produce`**
17
+ (create the first bundle from the code, docs, or what lives only in
18
+ people's heads). Nothing else applies yet.
16
19
  3. **Read the bundle's state** from the CLI, not by eyeballing:
17
20
  `okf validate <root>`, `okf lint <root>`, `okf loose <root>` — the plain
18
21
  text views, which are lighter than `--json` when you are reading a report
@@ -0,0 +1,42 @@
1
+ # Playbook: migrate — OKFy existing docs in place
2
+
3
+ Adopt documentation that already *is* the knowledge: frontmatter on, reserved
4
+ files in, every body kept **verbatim**. The output must be recognizably the
5
+ input — when the documents should instead be distilled into new concepts, that
6
+ is [produce.md](produce.md), not migrate. If the `okf` CLI is missing, stop and
7
+ follow [doctor.md](doctor.md) first.
8
+
9
+ Bodies are sacred: migrate never rewrites, reorders, or summarizes a body — the
10
+ one permitted edit besides prepending frontmatter is repointing a relative link
11
+ that a file move broke. <!-- rule:okf-migrate-verbatim -->
12
+ Read the modelling craft in [authoring.md](../reference/authoring.md) before a
13
+ non-trivial migration; its type and tag rules apply here unchanged.
14
+
15
+ 1. **Inventory from the validator, not by eyeballing.** `okf validate <dir>
16
+ --json` enumerates every file missing frontmatter or `type` and every
17
+ malformed reserved file — that list is the worklist, and the pass is done
18
+ when it reports zero.
19
+ 2. **Prepend frontmatter; do not touch the body below it.** Use the frontmatter
20
+ block of [templates/concept.md](../templates/concept.md): a small `type`
21
+ vocabulary derived from what the documents *are* (reuse before minting —
22
+ check `okf types <dir>` as you go), `title`/`description` from each
23
+ document's own heading and purpose line, `timestamp` from the document's own
24
+ date when it carries one, `tags` only where connective.
25
+ 3. **Keep the directory topology** — it is already domain knowledge. Default
26
+ one file = one concept. When a file shows split signals (two `type`s
27
+ fighting for the frontmatter, two audiences), flag it for a later `curate`
28
+ pass; never split, rename, or restructure during migration.
29
+ 4. **Reserved files.** A bundle-root `index.md` from
30
+ [templates/root-index.md](../templates/root-index.md) (frontmatter is
31
+ `okf_version: "0.1"` and nothing else), a nested `index.md` per directory
32
+ from [templates/index.md](../templates/index.md), and `log.md` with a dated
33
+ **Creation** entry naming where the documents came from.
34
+ 5. **Links.** The documents' existing relative links become the graph's edges —
35
+ verify they resolve inside the bundle and repoint only what a move broke.
36
+ Links pointing outside the bundle are tolerated (§5.3); leave them.
37
+ 6. **Close out** — walk the
38
+ [Closeout gate](../reference/authoring.md#closeout--the-finishing-gate):
39
+ `validate` zero errors, `lint` (pass `--stale-after` when you stamped
40
+ timestamps), `loose`, tag review, index eyeball. Then prove the promise:
41
+ each concept with its frontmatter block stripped is byte-identical to the
42
+ source document.
@@ -8,7 +8,8 @@ vocabulary, topology, links, citations — lives in
8
8
  2. Pick the source(s): **code** (derive concepts from source, READMEs, docstrings,
9
9
  config), **docs/wiki** (distill pages into concepts; cite the originals under
10
10
  `# Citations`), **manual** (decisions, playbooks, metrics that live only in
11
- people's heads).
11
+ people's heads). If the source documents should survive as the concepts
12
+ themselves — verbatim — that is [migrate.md](migrate.md), not produce.
12
13
  3. Choose a domain-based directory layout. One concept per file.
13
14
  4. Write each concept from [templates/concept.md](../templates/concept.md): a
14
15
  descriptive `type` from the bundle's vocabulary, recommended fields filled,
data/lib/okf/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OKF
4
- VERSION = "1.6.0"
4
+ VERSION = "1.7.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: okf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
@@ -87,6 +87,7 @@ files:
87
87
  - lib/okf/skill/playbooks/doctor.md
88
88
  - lib/okf/skill/playbooks/maintain.md
89
89
  - lib/okf/skill/playbooks/menu.md
90
+ - lib/okf/skill/playbooks/migrate.md
90
91
  - lib/okf/skill/playbooks/produce.md
91
92
  - lib/okf/skill/playbooks/search.md
92
93
  - lib/okf/skill/reference/APACHE-2.0.txt