okf 2.1.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 +56 -16
- data/README.md +197 -17
- data/lib/okf/version.rb +1 -1
- metadata +46 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ee1290010aa1d32e2f38408b2c630666cec67265f41e7c7186297274748120fa
|
|
4
|
+
data.tar.gz: a6b6218572fe7a74c38d0445940954c0fdbe591adab3e820d7de5aed71809828
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7d0af2ca85fd75d51587f513c53f667e77c13b3f407da10fb6463d921e3796ba5b6746fb77e5c5c11c26a700a54e00ee3e805310f98179cf328a858d7496195
|
|
7
|
+
data.tar.gz: c3a0276b516320e16f54cf3f647e3c6d6ea94625fd2341df6640903a7e5fc64b20c2a9e2b82065cf64519852db0cf2aec35cdc79ddad783852890a123c8e4911
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Capability
|
|
3
|
+
title: Companion agent skill (skill)
|
|
4
|
+
description: A SKILL.md plus references and templates, shipped inside the gem, that teaches an agent to author OKF.
|
|
5
|
+
resource: gems/okf/lib/okf/skill.rb
|
|
6
|
+
tags: [agent, install]
|
|
7
|
+
generated:
|
|
8
|
+
by: human:maintainer
|
|
9
|
+
at: 2026-08-17T12:00:00Z
|
|
10
|
+
sources:
|
|
11
|
+
- title: gems/okf/lib/okf/skill.rb
|
|
12
|
+
resource: https://github.com/serradura/okf/blob/main/gems/okf/lib/okf/skill.rb
|
|
13
|
+
- title: gems/okf/lib/okf/skill/SKILL.md
|
|
14
|
+
resource: https://github.com/serradura/okf/blob/main/gems/okf/lib/okf/skill/SKILL.md
|
|
15
|
+
- title: gems/okf/test/plugin/sync_test.rb
|
|
16
|
+
resource: https://github.com/serradura/okf/blob/main/gems/okf/test/plugin/sync_test.rb
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Overview
|
|
20
|
+
|
|
21
|
+
The gem carries the **OKF agent skill** — a `SKILL.md` with reference and
|
|
22
|
+
template files that teach a coding agent to *produce*, *migrate*, *maintain*,
|
|
23
|
+
*refine*, *consume*, *search*, *curate*, and *doctor* OKF (`@okf-eco format/okf-format`) bundles
|
|
24
|
+
and to drive the [CLI](../cli.md). The authoring judgment the executable can't encode lives here;
|
|
25
|
+
the executable handles the mechanics. Each verb routes to its own playbook
|
|
26
|
+
(`playbooks/`); the search playbook is progressive disclosure end to end —
|
|
27
|
+
ingest the index map, decide where to look, cut across with
|
|
28
|
+
[`okf search`](search.md), read only the winning bodies — and pointed questions
|
|
29
|
+
route to it first from the menu and consume playbooks. The two authoring
|
|
30
|
+
on-ramps stay distinct: `produce` distills sources into new concepts, while
|
|
31
|
+
`migrate` adopts existing documentation in place — frontmatter and reserved
|
|
32
|
+
files added, bodies kept **verbatim**, with `okf validate --json` as the
|
|
33
|
+
worklist — so a document survives conversion recognizably itself. Three more verbs
|
|
34
|
+
bound that loop rather than drive it: `curate` is structural upkeep as the bundle
|
|
35
|
+
*stands* — `validate` + `lint` + `loose` — and hands off to `maintain` the moment
|
|
36
|
+
the finding is that the *content*, not the structure, has drifted; `refine` is the
|
|
37
|
+
inverse hand-off — the content is right but the *shape* underserves retrieval —
|
|
38
|
+
and restructures for cohesion over the evidence the [read views](read-views.md)
|
|
39
|
+
compute (tag locality via `tags --by`, the hub origin test via `graph --hubs`),
|
|
40
|
+
always proposing before it applies; `doctor` is the
|
|
41
|
+
one playbook that assumes nothing, installing and verifying the [CLI](../cli.md)
|
|
42
|
+
before it examines the bundle. A no-argument run is a verb of its own — the menu
|
|
43
|
+
reads the signals and names the highest-value move without running one.
|
|
44
|
+
|
|
45
|
+
**Every playbook names the same first move**, and that took a correction. The
|
|
46
|
+
skill had prescribed one in seven places — bare `okf index`, `index --no-body`,
|
|
47
|
+
`dirs --depth 1` — across SKILL.md, four playbooks and the CLI reference, and
|
|
48
|
+
that disagreement *is* the deliberation an agent pays for on every retrieval. A
|
|
49
|
+
lookup table added to SKILL.md to pre-decide it made things worse: it duplicated
|
|
50
|
+
guidance already in the reference, contradicted the file it sat in, and carried
|
|
51
|
+
payload figures measured on one private bundle. It was reverted for the
|
|
52
|
+
subtraction it should have been. Every site now says `okf dirs` first, then
|
|
53
|
+
`okf index --dir <branch>` to descend — chosen structurally, because `dirs` emits
|
|
54
|
+
one row per directory where `index` emits one per concept even under `--no-body`,
|
|
55
|
+
so the two scale with different things. The reason is in the skill; the numbers
|
|
56
|
+
are not.
|
|
57
|
+
|
|
58
|
+
# `okf skill <dest>` installs it
|
|
59
|
+
|
|
60
|
+
`OKF::Skill.install` copies the skill into a destination you name — Claude Code's
|
|
61
|
+
`.claude`, an agent-agnostic `.agents`, wherever your agent looks. The rules are
|
|
62
|
+
deliberate:
|
|
63
|
+
|
|
64
|
+
- the **destination is required** — no magic default — so a user always decides
|
|
65
|
+
where the skill lands;
|
|
66
|
+
- it lands in a **`skills/okf/` folder** by default (`.claude` →
|
|
67
|
+
`.claude/skills/okf`), because an agent discovers a skill as
|
|
68
|
+
`<skills-dir>/<name>/SKILL.md` — so the skill settles in its own folder, not
|
|
69
|
+
loose among the others. A `<dest>` already ending in `skills` only gains the
|
|
70
|
+
`okf/` leaf; one already named `okf` is used as-is (idempotent); `--here`
|
|
71
|
+
pastes straight into `<dest>`, wherever it is;
|
|
72
|
+
- the resolved directory must be **empty unless `--force`**, so a customized
|
|
73
|
+
skill is never clobbered.
|
|
74
|
+
|
|
75
|
+
# One canonical copy, versioned with the gem
|
|
76
|
+
|
|
77
|
+
The skill ships **only** from `okf/lib/okf/skill/**` — that tree is the single source,
|
|
78
|
+
and `install` copies from it. Because the skill rides inside the gem, installing
|
|
79
|
+
the gem already puts the skill on the machine, and the skill's CLI reference can
|
|
80
|
+
**never drift** from the executable it was released with. Local installs
|
|
81
|
+
elsewhere are gitignored so they never masquerade as the source.
|
|
82
|
+
|
|
83
|
+
# Two more channels: the Claude Code plugin, and `skills/`
|
|
84
|
+
|
|
85
|
+
The repository doubles as a plugin marketplace, and the plugin carries a
|
|
86
|
+
**generated** copy of the same skill (`plugin/skills/okf`) — `rake skill:sync`
|
|
87
|
+
regenerates it after any skill edit or version bump, and a test fails the build
|
|
88
|
+
on drift, so the canonical-copy rule survives the second channel. Around the
|
|
89
|
+
skill the plugin adds a front-door command (`/okf:gem`) that is deliberately a
|
|
90
|
+
**pass-through shim**: it hands its arguments to the skill unchanged, so
|
|
91
|
+
`SKILL.md` stays the single router for every channel — the Commands table, the
|
|
92
|
+
intent inference, and the not-a-bundle `migrate` suggestion live only there,
|
|
93
|
+
where the drift test guards them, instead of in a second copy the test never
|
|
94
|
+
sees. The plugin also carries a PostToolUse hook that runs `okf validate` +
|
|
95
|
+
`okf lint` after every edit inside a bundle and hands the relevant findings
|
|
96
|
+
back as context. Nothing under `plugin/` ships in the gem.
|
|
97
|
+
|
|
98
|
+
The third channel is the generic one. A skill installer walks a repository's
|
|
99
|
+
`skills/` directory, so `skills/okf` is the same generated copy under the name
|
|
100
|
+
every such tool already looks for — `npx skills add serradura/okf` installs
|
|
101
|
+
it into any of the agents that tool supports, no gem and no Claude Code
|
|
102
|
+
required. It costs one line in `GENERATED_SKILL_COPIES` rather than a second
|
|
103
|
+
task, which is the point: **one canonical tree with N destinations is one
|
|
104
|
+
obligation, and a second task to remember is a second task to forget.** The
|
|
105
|
+
guard scales with it — `rake skill:verify` compares file lists and SHA-256
|
|
106
|
+
checksums for every destination and `build` depends on it, so a copy cannot be
|
|
107
|
+
released stale, whatever channel it feeds.
|
|
108
|
+
|
|
109
|
+
The channels are not equivalent, and the difference is the version they carry.
|
|
110
|
+
The gem's copy is the release's, pinned to the executable beside it; the plugin's
|
|
111
|
+
follows the marketplace; `skills/` tracks this repository's default branch. A
|
|
112
|
+
consumer who needs the skill and the CLI to agree should take the gem's.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Capability
|
|
3
|
+
title: Bundles list (the hub's /b/ page)
|
|
4
|
+
description: The hub's /b/ page — every bundle it knows about with its size, health and default marker — and the four POST routes that change the registry, which the graph page's Bundles panel drives.
|
|
5
|
+
resource: gems/okf/lib/okf/server/hub.rb
|
|
6
|
+
tags: [server, registry, hub, ui]
|
|
7
|
+
generated:
|
|
8
|
+
by: human:maintainer
|
|
9
|
+
at: 2026-07-21T16:00:00Z
|
|
10
|
+
sources:
|
|
11
|
+
- title: gems/okf/lib/okf/server/hub.rb
|
|
12
|
+
resource: https://github.com/serradura/okf/blob/main/gems/okf/lib/okf/server/hub.rb
|
|
13
|
+
- title: gems/okf/lib/okf/cli/server.rb
|
|
14
|
+
resource: https://github.com/serradura/okf/blob/main/gems/okf/lib/okf/cli/server.rb
|
|
15
|
+
- title: gems/okf/lib/okf/registry.rb
|
|
16
|
+
resource: https://github.com/serradura/okf/blob/main/gems/okf/lib/okf/registry.rb
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Why it exists
|
|
20
|
+
|
|
21
|
+
The [registry](../registry.md) has always been a terminal thing: `okf registry
|
|
22
|
+
set`, `del`, `default`, `rename`. That is the right surface for the people who
|
|
23
|
+
write the bundles, and the wrong one for the people who read them. A meeting with
|
|
24
|
+
non-technical readers settled it — the registry needed a point-and-click
|
|
25
|
+
surface, and the [server](graph-server.md) was already most of the way there.
|
|
26
|
+
|
|
27
|
+
The `/b/` page used to be a bare list of links. It became the browser
|
|
28
|
+
counterpart of the TUI's bundles view — every fact needed to choose between
|
|
29
|
+
bundles, and forms to change the set.
|
|
30
|
+
|
|
31
|
+
Then the [graph page](graph-server.md) grew a **Bundles panel** behind the rail's
|
|
32
|
+
⚙, and for a while both surfaces carried the same four verbs. Two
|
|
33
|
+
implementations of one contract is the thing that drifts, so the forms came out
|
|
34
|
+
of `/b/` and the routes stayed. The split that survives is a clean one: `/b/`
|
|
35
|
+
answers *which bundles are there*, from a page you can land on with no bundle
|
|
36
|
+
open at all, and the panel answers *change this one* where the reader already
|
|
37
|
+
is. Managing a set is something you do while reading it, not on a detour to a
|
|
38
|
+
page you had to know existed.
|
|
39
|
+
|
|
40
|
+
# What a row says
|
|
41
|
+
|
|
42
|
+
One row per bundle the server *knows about*, which is deliberately not the same
|
|
43
|
+
as one per bundle it *hosts*. A registry entry whose folder was deleted cannot be
|
|
44
|
+
served, and leaving it off the page answers "where did my bundle go?" with
|
|
45
|
+
silence; it shows, muted, with `folder is gone` and no link.
|
|
46
|
+
|
|
47
|
+
Each row carries the title, the `@slug` you would type at the CLI, the folder,
|
|
48
|
+
the concept count, and a **health verdict** — `ok`, `warn`, `error` — drawn as a
|
|
49
|
+
3px rule on the row's left edge. That rule is the accent bar under the page's own
|
|
50
|
+
heading, stood on end and put to work; colour only reinforces it, and the word
|
|
51
|
+
beside it is the message, so nothing on the page depends on being able to see
|
|
52
|
+
red. The verdict keeps the [validate/lint separation](validator.md): a curation
|
|
53
|
+
finding is a warning and the bundle stays open, and only a non-conformant bundle
|
|
54
|
+
reads as broken.
|
|
55
|
+
|
|
56
|
+
Rows are matched to entries by **directory**, not by slug. A rename changes the
|
|
57
|
+
slug and nothing else, and a row that lost its identity over a rename is the bug
|
|
58
|
+
that avoids.
|
|
59
|
+
|
|
60
|
+
# Writes, and the four locks on them
|
|
61
|
+
|
|
62
|
+
Four routes change anything — `POST /registry/default | rename | remove | add` —
|
|
63
|
+
and each passes four gates before it runs. They are the only non-GET routes the
|
|
64
|
+
server has:
|
|
65
|
+
|
|
66
|
+
1. **Is this server writable at all?** A loopback bind is, without a flag: the
|
|
67
|
+
audience this page was built for should not need a command line to use the
|
|
68
|
+
page they were pointed at, and `okf server --read-only` is how they decline it.
|
|
69
|
+
Any other address is refused outright, with no flag that opens it: `--bind
|
|
70
|
+
0.0.0.0` is how a personal tool becomes a public one, and a write surface does
|
|
71
|
+
not follow it there at all. A read-only server offers no controls *and*
|
|
72
|
+
refuses the request that skipped them — hiding a button is a UI, refusing the
|
|
73
|
+
request is the boundary.
|
|
74
|
+
2. **Is there a registry to write to?** An ephemeral hub (`okf server ./a ./b`)
|
|
75
|
+
is serving directories somebody typed and has no list to edit — `409`, and the
|
|
76
|
+
page says so rather than leaving the missing controls a mystery.
|
|
77
|
+
3. **Is the verb one of the four?** The path is user input, and "call whatever
|
|
78
|
+
method the path names" is how a router becomes an `eval`. A frozen list, not
|
|
79
|
+
a lookup.
|
|
80
|
+
4. **Did this come from this page?** Same-origin *and* a per-boot token. Neither
|
|
81
|
+
alone is enough: the token lives in a page, and a page is a thing another
|
|
82
|
+
site can get a reader to submit; Origin alone would trust every
|
|
83
|
+
tab the browser has open on this host. An unstated origin is refused rather
|
|
84
|
+
than assumed. Per-boot rather than per-session because the hub has no sessions
|
|
85
|
+
and wants none — a cookie jar is a subsystem to defend for a page four people
|
|
86
|
+
see.
|
|
87
|
+
|
|
88
|
+
A success writes the file, **rebuilds the hub's bundles and apps from disk**, and
|
|
89
|
+
answers with the outcome. The rebuild is the part that is easy to skip and
|
|
90
|
+
impossible to skip safely: a write that leaves the running server on the old set
|
|
91
|
+
is a lie the next click believes.
|
|
92
|
+
|
|
93
|
+
Every answer is JSON, and Accept decides nothing. It used to be one of two
|
|
94
|
+
renderings — a `303` back to `/b/` for the forms, so a reload never re-posted,
|
|
95
|
+
and JSON for the panel's `fetch()`. With the forms gone there is one caller, so
|
|
96
|
+
there is one shape; asking for HTML does not resurrect a page-shaped answer that
|
|
97
|
+
nothing would read. The refusal messages are the core's own — a reserved slug, a
|
|
98
|
+
collision, a slug nothing carries all raise `OKF::Error` with a sentence written
|
|
99
|
+
for a person, and repeating that judgement in the server is how the two come to
|
|
100
|
+
disagree.
|
|
101
|
+
|
|
102
|
+
# The page carries no script, and nothing to post
|
|
103
|
+
|
|
104
|
+
No JavaScript, no build step, and now no forms and no token either: a page with
|
|
105
|
+
nothing to post has no business holding the credential. What is left is what only
|
|
106
|
+
this page can be — the list, the place `/` redirects from when no bundle is
|
|
107
|
+
named, the way back from the [404](graph-server.md), and the **empty state**. That
|
|
108
|
+
last one is why it cannot simply be deleted along with its forms: a hub with zero
|
|
109
|
+
bundles serves no graph page, so there is no page for the panel to live on, and
|
|
110
|
+
something still has to say what happened and how to fix it.
|
|
111
|
+
|
|
112
|
+
**There is no Add anywhere**, on either surface. A browser cannot hand over a
|
|
113
|
+
filesystem path — the File System Access API yields an opaque handle, never a
|
|
114
|
+
path, and is Chromium-only besides — and registering is the agent's act. The
|
|
115
|
+
route is still there because `okf registry set` is not the only caller that could
|
|
116
|
+
want it, but nothing in the UI reaches it.
|
|
117
|
+
|
|
118
|
+
# Verification
|
|
119
|
+
|
|
120
|
+
`okf/test/integration/server/hub_writes_test.rb` is the critical layer: every verb's
|
|
121
|
+
happy path, every refusal, and each of the four gates, asserting both that the
|
|
122
|
+
registry file changed *and* that the live hub reflects it without a restart.
|
|
123
|
+
`okf/test/browser/specs/bundles-panel.spec.js` drives the same verbs in Chromium
|
|
124
|
+
through the panel, against a registry-backed server with its own `$OKF_HOME` —
|
|
125
|
+
serial, and each spec puts back what it changed, because they share one live
|
|
126
|
+
registry.
|
|
127
|
+
<!-- rule:okf-prove-the-write-lands -->
|
|
128
|
+
|
|
129
|
+
A browser pass over these writes earned its place immediately, back when they
|
|
130
|
+
were forms: it caught an HTML `pattern` attribute whose character class was valid
|
|
131
|
+
as a Ruby regexp and invalid under the `v` flag a browser compiles it with, so
|
|
132
|
+
every keystroke in the rename field threw a `SyntaxError` no integration
|
|
133
|
+
assertion could see.
|