SuperAPI AI Directory

curator

General & other

View repository

Updated 10-16 01:19

About this skill

Wiki Curator

Overview

The curator is the operational half of Lumen. It turns memory-source records into conservative Markdown wiki updates, and it lints the wiki for structural decay. It never calls providers, never deletes pages, and never overwrites operator-confirmed facts.

Pair it with lumen:wiki for methodology (OKF frontmatter, ingest/query/lint procedures). This skill is the CLI and adapter layer.

When to Use

Use this skill when the user wants to:

  • Ingest recent memory into the wiki (run) or preview that ingest (report)
  • Lint or validate wiki structure
  • Search wiki pages by keyword, alias, or tag
  • Configure which memory source the curator reads

Wiki Location

Resolve the wiki path in this order:

  1. --wiki CLI override
  2. paths.wiki_path in plugin config (shared/config/lumen.yaml or --config)
  3. $WIKI_PATH environment variable
  4. Default ~/wiki

Plugin config (lumen.yaml)

Default file: <plugin>/shared/config/lumen.yaml. Override with --config or LUMEN_CONFIG.

paths:
  wiki_path: ~/wiki          # null → $WIKI_PATH → ~/wiki

curator:
  timezone: Asia/Singapore
  max_write_pages: 20        # 0 or negative disables the cap
  memory_source: sessions    # sessions | auto | json-file | mnemosyne | none

auto prefers sessions when a readable Hermes state.db exists (the conversation history is the ground truth; Mnemosyne holds derived notes), then Mnemosyne when hermes is on PATH, falling back to the json-file adapter if the export fails. none disables ingest (file-only lint/search still work).

Adapter layer

${HERMES_SKILL_DIR}/scripts/adapters.py is the read-only memory boundary. Adapters emit SourceItem records (source_id, source_kind, title, text, timestamp, tags, people, entities, projects, raw). Nothing writes back to a memory store.

Adapter Source Notes
sessions Hermes state.db (conversation history) Read-only SQLite; user messages paired with the first assistant reply; gateway-origin JSON envelopes stripped. Default source.
json-file <wiki>/.knowledge/memory.json Tolerant record shapes (records map or list). Missing file → [].
mnemosyne hermes mnemosyne export --output <tmp> Parses working_memory + episodic_memory. Subprocess failure → [].
none empty Explicit opt-out.

Record fields. people / entities / projects take a list for several names; a plain string is one name ("Acme, Inc." stays one entity). tags may be a list or a comma-separated string. Records without an id get a content-derived id (memory_<digest> of timestamp and text), so reordering or inserting records does not re-ingest them. When a record names no people/entities/projects, capitalised words in its title/text are used as entity hints; a sentence-initial word ("Met with…", "Sent…") only counts if the same word also appears capitalised mid-sentence, and the Untitled placeholder title is never scanned.

Extension point (generic-json). Any provider that can emit the json-file memory.json shape (a records mapping or a list of record objects, with tolerant people/entities/projects keys) can be dropped in as <wiki>/.knowledge/memory.json and selected with memory_source: json-file. A dedicated generic-json adapter that takes an arbitrary export path is the documented next step; do not add provider-specific imports.

CLI

Script: ${HERMES_SKILL_DIR}/scripts/wiki_curator.py (Hermes substitutes ${HERMES_SKILL_DIR} with this skill's directory, so the path works from any cwd). Run with system python3 (stdlib + PyYAML).

CURATOR="${HERMES_SKILL_DIR}/scripts/wiki_curator.py"

python3 "$CURATOR" run --since 24h          # ingest (writes wiki pages)
python3 "$CURATOR" run --since 24h --dry-run
python3 "$CURATOR" report --since 7d        # planned changes, no writes
python3 "$CURATOR" validate                 # lint; exit 1 on ERROR
python3 "$CURATOR" lint                     # same checks
python3 "$CURATOR" lint --summary           # counts only
python3 "$CURATOR" search "Acme" --format json --limit 10
python3 "$CURATOR" search "Acme" --format text --wiki ~/wiki

Global flags: --config <lumen.yaml>, --wiki <path> (also accepted after the subcommand).

--since accepts 90m, 24h, 7d, 2w; anything else is a usage error (exit 2). Runtime errors such as a wiki subdirectory that is a symlink out of the wiki print error: … and exit non-zero.

Read-only vs mutating: lint, validate, report, and search are read-only. run writes. run --dry-run previews. The curator never deletes pages.

Conservative write policy

  • Create or update people / project / entity / daily pages from source items only
  • Preserve operator-confirmed facts; append observations with [source: id]
  • Refresh only the <!-- lumen:auto:start --> … <!-- lumen:auto:end --> block of index.md and overview.md (hand-written content outside the markers is preserved; a file without markers gets a block appended); append log.md
  • Record text, titles and names are flattened to one line with [source: / [[ / leading # neutralised, so memory content cannot forge sections, source markers or links
  • Never overwrite an existing page title or created value
  • Skip an existing page whose YAML frontmatter does not parse: it is left byte-for-byte unchanged, a skip line naming the page appears in the run report (and a warning on stderr), and the source is retried on the next run once the page is fixed
  • Rewritten files keep their existing permission bits; new files get 0666 & ~umask
  • Cap source items per run at curator.max_write_pages (default 20; 0 or negative disables the cap)
  • Backup the wiki tree to <wiki>/.lumen/backup/<timestamp>/ before large batches (>5 items). .lumen/ is excluded from index and overview regeneration.

OKF v0.2

Every curated .md page needs parseable YAML frontmatter with a non-empty type field. See lumen:wiki for the full schema. The curator assigns seq on create and preserves aliases / relations.

Lint checks

  • Missing or malformed frontmatter (ERROR)
  • Missing type (ERROR)
  • Broken [[wikilinks]] (WARN)
  • Duplicate titles (WARN)
  • Pages absent from index.md (WARN)
  • Orphans with no inbound links (INFO)
  • Stale pages (updated >90 days) (INFO)

File naming

Lowercase hyphenated ASCII slugs: acme-logistics.md. Accents are folded (Zoë → zoe.md); a name with no ASCII letters or digits (张伟) gets untitled-<first 8 hex of sha256(name)>.md, stable across runs and distinct per name. Wikilinks use the page title, so [[张伟]] resolves. Avoid generic names like notes.md.

Common pitfalls

  1. Skipping orientation (purpose.md, SCHEMA.md, index.md, recent log.md)
  2. Creating duplicate entity pages without searching first
  3. Dumping raw notes as curated knowledge
  4. No frontmatter / missing type
  5. Unlinked pages that lint later reports as orphans

Verification checklist

  • Wiki path resolved from plugin config, then $WIKI_PATH, then ~/wiki
  • memory_source matches the host install (auto / json-file / mnemosyne / none)
  • run --dry-run reviewed before a mutating run
  • Lint reports file paths and severity
  • Query answers cite wiki pages