These three fields are what power the wiki reader: the Relations panel's type
badges and headers, and the in-editor link hover previews. Running enrich makes
an ordinary folder of Markdown read like a typed, navigable knowledge base —
this is generic Open Knowledge Format frontmatter, not an
OKF-specific format. No marker file or manifest is required.
-
Pick the target(s). Accept either a single absolute file path or a
directory. If a directory, ask the user to confirm scope before walking it.
Only operate on Markdown files (.md). Stay inside projects or ~/Notesage
— do not enrich files from an arbitrary Explorer folder unless the user
explicitly asks.
-
Scan each document to find which fields are missing and to read the body
the model needs:
execute_skill_script("okf-enrich", "scripts/scan.mjs", [file_path])
Output JSON to stdout:
{
"file": "/abs/path/to/doc.md",
"missing": ["type", "title", "description"],
"present": { "title": "Existing Title" },
"status": "incomplete",
"body": "first ~4000 chars of the document body (frontmatter stripped)"
}
status values:
"incomplete" — at least one of type/title/description is missing
"complete" — all three already present; nothing to do, skip this file
For a directory, run scan.mjs once per .md file (the script takes one
path), or pass --list <dir> to enumerate the .md files first:
execute_skill_script("okf-enrich", "scripts/scan.mjs", ["--list", dir_path])
-
Generate the missing fields with structured output. For each document
with status: "incomplete", produce ONLY the missing fields using
schema-constrained generation. The shape is guaranteed by the JSON schema —
the model cannot return a malformed object. Use a schema that includes only
the keys listed in missing, for example (when all three are missing):
{
"type": "object",
"additionalProperties": false,
"required": ["type", "title", "description"],
"properties": {
"type": { "type": "string", "description": "one lowercase single-token noun for the document kind" },
"title": { "type": "string", "description": "concise human-readable title" },
"description": { "type": "string", "description": "one-sentence summary of the document" }
}
}
Feed the model the body returned by scan.mjs and ask it to return the
object. Notesage routes this through generateStructured() /
buildJsonSchemaResponseFormat() (see
docs/features/ai-providers.md → "Structured Output (Schema-Constrained
Generation)"). On local_bundled / openai_compatible / ollama the schema
is enforced at the token level (GBNF/XGrammar), so output is guaranteed valid.
Keep values terse: type is a single lowercase token, title a short phrase,
description a single sentence. Do not include fields that were already
present — only the missing ones.
-
Merge the generated fields back into the document. Pass the model's JSON
to apply.mjs. The script merges the new fields into the existing frontmatter
— filling only keys that are absent, never overwriting — and prints the full
merged file content to stdout. It does not write to disk.
execute_skill_script("okf-enrich", "scripts/apply.mjs", [file_path, fields_json])
Where fields_json is the model's JSON object as a string, e.g.
{"type":"note","title":"Q3 Planning","description":"Notes from the Q3 planning session."}.
Output JSON to stdout:
{
"file": "/abs/path/to/doc.md",
"applied": ["type", "description"],
"skipped": ["title"],
"content": "---\n…merged frontmatter…\n---\n\n…body…\n"
}
applied — fields that were missing and got filled
skipped — fields the model returned that were already present (left untouched)
content — the complete merged document to write
-
Write the file through the approval path. Take the content from step 4
and write it with the write_file tool:
write_file(path=file_path, content=<content from apply.mjs>)
write_file requires user approval — this is intentional. Never write the
file from inside a skill script; enrich only computes the merged content and
leaves the actual disk write to the approval-gated write_file tool. If the
user denies the write, report it and move on without retrying.
-
Report the result. For each document tell the user which fields were
filled and with what values, and list any skipped (already-complete) files.