docs(project): the server is the standard way in, the skill the supplement
`okf project`'s closing text and the README's first screen now say it in that order: register `okf mcp --root` once, and it answers from every project and reaches subagents; the skill beside the bundle is for someone who would rather register nothing; neither is made again when a bundle is rebuilt. Two tests hold the order in both places. The README's stale `<id>-consume` skill path is corrected to `okf-consume-any`. v1.1 order F, part F3. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
718c064279
commit
570496470b
5 changed files with 56 additions and 19 deletions
|
|
@ -1540,6 +1540,12 @@ R761 **8** (S1-S6 + KP + KN), vegnormal **32** questions / **43**
|
||||||
of them, so over a folder it is REFUSED by name with exit 2
|
of them, so over a folder it is REFUSED by name with exit 2
|
||||||
(`consume.FOLDER_FLAGS` is the allowlist), never dropped; `--bundle-id` on a
|
(`consume.FOLDER_FLAGS` is the allowlist), never dropped; `--bundle-id` on a
|
||||||
bundle path is refused the same way. A bundle path reads exactly as before.
|
bundle path is refused the same way. A bundle path reads exactly as before.
|
||||||
|
- **THE SERVER IS THE STANDARD WAY IN AND THE SKILL THE SUPPLEMENT (v1.1 F3,
|
||||||
|
operator 2026-09-21).** `okf project`'s closing text and README's first
|
||||||
|
screen say it in that order: register `okf mcp --root` once (every project,
|
||||||
|
subagents too); the skill beside the bundle is for someone who would rather
|
||||||
|
register nothing; neither is made again when a bundle is rebuilt. Two tests
|
||||||
|
hold the ORDER, not just the presence, in both places.
|
||||||
- **`okf card <bundle>` and the generic skill are the one-to-many form.** The card is one bundle's identity, concept count,
|
- **`okf card <bundle>` and the generic skill are the one-to-many form.** The card is one bundle's identity, concept count,
|
||||||
conditional-field counts and whole-bundle cost as JSON, **DERIVED on every run
|
conditional-field counts and whole-bundle cost as JSON, **DERIVED on every run
|
||||||
and never written into the bundle** -- storing it would move the bytes of all
|
and never written into the bundle** -- storing it would move the bytes of all
|
||||||
|
|
|
||||||
23
README.md
23
README.md
|
|
@ -16,22 +16,23 @@ uv tool install "llm-ingestion-okf[extract] @ git+https://git.fromaitochitta.com
|
||||||
## Use it
|
## Use it
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
okf project ~/my-documents # folder in: bundle + Claude Code skill, in this directory
|
okf project ~/my-documents # folder in: a bundle under ./.okf, and a skill beside it
|
||||||
claude # start Claude Code here
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Or connect every bundle at once.** Register the server once, on user scope,
|
**The standard way in is the server.** Register it once, on user scope,
|
||||||
and every project you open can ask any bundle under that directory — no skill
|
pointing at the directory that holds your projects. Every project you open can
|
||||||
to install per project, and nothing to regenerate when a bundle is rebuilt.
|
then ask any bundle under it, subagents included — they inherit MCP tools and
|
||||||
You run this line; `okf` never starts Claude Code:
|
not skills — and a bundle added or rebuilt is seen by the next call. You run
|
||||||
|
this line; `okf` never starts Claude Code:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
claude mcp add --scope user okf -- okf mcp --root ~/okf
|
claude mcp add --scope user okf -- okf mcp --root ~/projects
|
||||||
```
|
```
|
||||||
|
|
||||||
Subagents inherit MCP tools and do not inherit skills, so the server is also
|
**The skill is the supplement**, for when you would rather register nothing:
|
||||||
the only way the same working method reaches an arm running below the main
|
`okf project` writes it beside the bundle, so starting `claude` in that
|
||||||
thread.
|
directory is enough. It reads every bundle under `./.okf` with the same code the
|
||||||
|
server runs. Neither has to be made again when a bundle is rebuilt.
|
||||||
|
|
||||||
Then ask in plain language. Three shapes of request work, and the skill states
|
Then ask in plain language. Three shapes of request work, and the skill states
|
||||||
the rules for each:
|
the rules for each:
|
||||||
|
|
@ -1236,7 +1237,7 @@ claude
|
||||||
```
|
```
|
||||||
|
|
||||||
`okf project` writes the bundle to `.okf/<id>/` and a skill to
|
`okf project` writes the bundle to `.okf/<id>/` and a skill to
|
||||||
`.claude/skills/<id>-consume/` in the **current directory**, then prints what it
|
`.claude/skills/okf-consume-any/` in the **current directory**, then prints what it
|
||||||
read, what it wrote, and which documents a question cannot reach. Start `claude`
|
read, what it wrote, and which documents a question cannot reach. Start `claude`
|
||||||
in that directory and ask in plain language; the generated skill runs the
|
in that directory and ask in plain language; the generated skill runs the
|
||||||
pre-pass and the contract check itself and marks every claim with its source.
|
pre-pass and the contract check itself and marks every claim with its source.
|
||||||
|
|
|
||||||
|
|
@ -178,16 +178,19 @@ def summarise(
|
||||||
lines.extend(
|
lines.extend(
|
||||||
[
|
[
|
||||||
"",
|
"",
|
||||||
f"NEXT: start claude again in {out} and ask your question.",
|
"NEXT -- the standard way in is the server. Register it ONCE; you run",
|
||||||
"",
|
f"this line, {CLI_ID} never starts claude:",
|
||||||
"To reach this bundle -- and every other bundle under one directory --",
|
|
||||||
"from ANY project, register the server once instead. You run this line;",
|
|
||||||
f"{CLI_ID} never starts claude:",
|
|
||||||
"",
|
"",
|
||||||
f" claude mcp add --scope user okf -- okf mcp --root {out.parent}",
|
f" claude mcp add --scope user okf -- okf mcp --root {out.parent}",
|
||||||
"",
|
"",
|
||||||
"Then no skill has to be installed per project, and nothing has to be",
|
"It then answers from every project, reaches subagents too, and sees",
|
||||||
"regenerated when a bundle is rebuilt.",
|
"every bundle under that directory -- one added or rebuilt later included.",
|
||||||
|
"",
|
||||||
|
"The skill written here is the supplement, for when you would rather",
|
||||||
|
f"register nothing: start claude in {out} and ask. It reads every",
|
||||||
|
f"bundle under {out / BUNDLE_DIR} with the same code.",
|
||||||
|
"",
|
||||||
|
"Neither has to be made again when a bundle is rebuilt.",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,33 @@ def test_the_project_summary_says_what_to_do_next_with_the_server(tmp_path: Path
|
||||||
assert "claude mcp add --scope user okf -- okf mcp --root" in summary
|
assert "claude mcp add --scope user okf -- okf mcp --root" in summary
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_project_summary_puts_the_server_first_and_the_skill_second(tmp_path: Path) -> None:
|
||||||
|
"""v1.1 F3: the server is the standard way in, the skill the supplement."""
|
||||||
|
folder = tmp_path / "Dokumenter"
|
||||||
|
folder.mkdir()
|
||||||
|
(folder / "krav.md").write_text(
|
||||||
|
"## 4 Grunnforhold\n\nGrunnen er morene over berg.\n", encoding="utf-8", newline=""
|
||||||
|
)
|
||||||
|
out = tmp_path / "project"
|
||||||
|
_, _, summary = project.create(folder, out=out)
|
||||||
|
server = summary.index("claude mcp add --scope user okf -- okf mcp --root")
|
||||||
|
skill = summary.index(f"start claude in {out}")
|
||||||
|
assert server < skill
|
||||||
|
assert "standard" in summary[:server]
|
||||||
|
assert "supplement" in summary[server:]
|
||||||
|
assert "Neither has to be made again when a bundle is rebuilt" in summary
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_readme_first_screen_puts_the_server_first_and_the_skill_second() -> None:
|
||||||
|
readme = (PROJECT_ROOT / "README.md").read_text(encoding="utf-8")
|
||||||
|
first_screen = readme.split("## Known limitations", 1)[0]
|
||||||
|
server = first_screen.index("claude mcp add --scope user okf -- okf mcp --root")
|
||||||
|
skill = first_screen.index("The skill is the supplement")
|
||||||
|
assert server < skill
|
||||||
|
assert "standard way in" in first_screen[:server]
|
||||||
|
assert "Neither has to be made again" in first_screen
|
||||||
|
|
||||||
|
|
||||||
def test_a_project_bundle_is_where_a_root_server_finds_it(tmp_path: Path) -> None:
|
def test_a_project_bundle_is_where_a_root_server_finds_it(tmp_path: Path) -> None:
|
||||||
"""`--root <the directory holding projects>` must reach `<project>/.okf/<id>`.
|
"""`--root <the directory holding projects>` must reach `<project>/.okf/<id>`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ def test_the_summary_names_the_documents_that_landed_whole(folder: Path, tmp_pat
|
||||||
assert "notat.md" in summary
|
assert "notat.md" in summary
|
||||||
assert "krav.md" not in summary
|
assert "krav.md" not in summary
|
||||||
assert "[sourced-not-sufficient]" in summary
|
assert "[sourced-not-sufficient]" in summary
|
||||||
assert f"NEXT: start claude again in {out}" in summary
|
assert f"start claude in {out}" in summary
|
||||||
|
|
||||||
|
|
||||||
def test_a_document_that_is_in_the_bundle_is_not_reported_as_missing(
|
def test_a_document_that_is_in_the_bundle_is_not_reported_as_missing(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue