From cogni-knowledge
Bootstrap a cogni-knowledge knowledge base — a wiki base + a binding manifest that records every research project deposited into it. Scaffolds the wiki skeleton natively (the wiki engine is vendored; no separate plugin required) if it does not exist, then writes .cogni-knowledge/binding.json. Use this skill whenever the user says 'set up a knowledge base', 'start a knowledge base on X', 'bootstrap a wiki-first research base', 'new knowledge base for X', 'create a knowledge base', or 'wiki-first research setup'. After setup, run the inverted pipeline (knowledge-plan → knowledge-curate → knowledge-fetch → knowledge-ingest → knowledge-compose → knowledge-verify → knowledge-finalize) to deposit research syntheses into the base.
How this skill is triggered — by the user, by Claude, or both
Slash command
/cogni-knowledge:knowledge-setupThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Bootstrap a cogni-knowledge knowledge base. A knowledge base is one directory that holds both a cogni-wiki (`.cogni-wiki/config.json`) and a cogni-knowledge binding manifest (`.cogni-knowledge/binding.json`). The wiki is the substrate; the binding records which research projects have contributed to it.
Bootstrap a cogni-knowledge knowledge base. A knowledge base is one directory that holds both a cogni-wiki (.cogni-wiki/config.json) and a cogni-knowledge binding manifest (.cogni-knowledge/binding.json). The wiki is the substrate; the binding records which research projects have contributed to it.
This skill is a thin orchestrator. It scaffolds the wiki skeleton natively — the wiki engine is vendored under scripts/vendor/cogni-wiki/, so setup dispatches no cogni-wiki:wiki-setup skill. The cogni-knowledge value-add is the binding manifest plus the one-command workflow.
Read ${CLAUDE_PLUGIN_ROOT}/references/differentiation-thesis.md once at the start of a session to anchor on why wiki-first matters; read ${CLAUDE_PLUGIN_ROOT}/references/delegation-contract.md to remember what cogni-knowledge owns vs. delegates.
/cogni-knowledge:knowledge-setup--reframe (re-runs the charter interview against the existing binding; no hand-editing binding.json).cogni-knowledge/binding.json — report the existing binding and stop. Re-initialisation is destructive; surface the existing slug and let the user decide.cogni-research:research-setup directly. cogni-knowledge is opinionated about accumulation; cogni-research stays available as a sibling plugin for one-shot reports.| Parameter | Required | Description |
|---|---|---|
--knowledge-slug | Yes (prompted) | Kebab-case identifier for the knowledge base, e.g. eu-ai-act. Used for the directory name (cogni-knowledge/<slug>/) and the knowledge_slug field in the binding. |
--knowledge-title | Yes (prompted) | Human-readable title, e.g. "EU AI Act knowledge base". Used as the wiki's name in .cogni-wiki/config.json. |
--knowledge-root | No | Override the default knowledge-base directory. Defaults to cogni-knowledge/<knowledge-slug>/ (relative to the current working directory). Both the wiki and the binding live inside this directory. |
--description | No | One-sentence description written into .cogni-wiki/config.json. |
--publisher-base-url | No | Written into .cogni-wiki/config.json as publisher_base_url. Used as last-resort fallback URL when wiki pages have no per-page publisher URL. |
--market | No | Default market for this knowledge base. One of: dach, de, fr, it, pl, nl, es, us, uk, eu. Persisted to binding.json::research_defaults.market; inherited by every knowledge-plan run. Resolved interactively in Step 2.5 when omitted (default dach). |
--output-language | No | Default output language (two-letter code) for this knowledge base. Persisted to binding.json::research_defaults.output_language; inherited by every knowledge-plan run. Resolved interactively in Step 2.5 when omitted — defaults to the chosen market's registry default_output_language (e.g. dach→de, fr→fr, eu→en). |
--prose-density | No | Default prose density (standard/executive) persisted to binding.json::research_defaults.prose_density. Flag-or-default — not prompted in Step 2.5 (safe default executive). |
--tone | No | Default writing tone persisted to binding.json::research_defaults.tone (see ${CLAUDE_PLUGIN_ROOT}/references/writing-tones.md). Flag-or-default — not prompted (safe default objective). |
--citation-format | No | Default citation format persisted to binding.json::research_defaults.citation_format (ieee/chicago wired; apa/mla/harvard staged). Flag-or-default — not prompted (safe default ieee). |
--target-words | No | Default soft target word count persisted to binding.json::research_defaults.target_words. Flag-or-default — not prompted (safe default 2000). |
--charter-domain | No | One sentence: what this knowledge base is about. Persisted to binding.json::charter.domain (schema 0.1.4). Resolved interactively in Step 2.5 when omitted (engages the charter interview). |
--charter-audience | No | Primary reader of the syntheses this base produces. Persisted to binding.json::charter.audience. Resolved interactively in Step 2.5 when omitted. |
--charter-scope | No | In/out boundaries — geography / segment / horizon, one line. Persisted to binding.json::charter.scope. Resolved interactively in Step 2.5 when omitted. |
--open-themes | No | Pipe-separated seed-theme backlog (e.g. "high-risk systems|conformity assessment|GPAI"). Persisted to binding.json::topic_lineage.open_themes[]; surfaces as the candidate menu for the first research question. Resolved interactively in Step 2.5 when omitted. |
--no-charter | No | Skip the Step 2.5 charter interview AND the Step 5 first-question on-ramp. Use for automation / a flag-only init. The charter fields fall through to "" and open_themes[] to [] (a complete, schema-valid 0.1.4 binding either way). |
--no-prelim-search | No | Keep the Step 2.5 charter interview but skip its optional preliminary scoping scan (stays offline). Same semantics as knowledge-plan --no-prelim-search. |
--reframe | No | Re-steer an existing base instead of bootstrapping a new one. Re-runs the Step 2.5 charter interview against the existing binding and writes the updated charter in place via knowledge-binding.py set-charter (a partial update — only the fields you change). Inverts Step 1's pre-flight: requires an existing binding and aborts when none is found. Skips wiki setup (Steps 2/3), the init call (Step 4), and the Step 5 first-question on-ramp. The charter's data shape (schema 0.1.4) is unchanged. |
If --knowledge-slug or --knowledge-title is missing, ask the user once with AskUserQuestion (call ToolSearch(query="select:AskUserQuestion") to load the schema if needed). Do not invent slugs or titles silently.
cogni-knowledge bundles its wiki engine: the vendored copy under scripts/vendor/cogni-wiki/ is resolved vendored-first by every wiki-touching step, and this skill scaffolds the wiki skeleton natively (Step 3). There is no cogni-wiki plugin install to probe and no hard dependency to abort on — setup runs end-to-end with nothing else installed. Proceed directly to Step 1.
--knowledge-root was passed, use it as-is.knowledge_root = cogni-knowledge/<knowledge-slug>/ relative to the current working directory — the standard cogni-plugin convention (cogni-{plugin}/{project-slug}/), matching cogni-wiki/{slug}/.--reframe): if <knowledge_root>/.cogni-knowledge/binding.json already exists, read it, report the existing knowledge_slug/title/wiki_path, and stop. Do not overwrite.--reframe mode (re-steer): the inverse. The binding must exist. If <knowledge_root>/.cogni-knowledge/binding.json is missing, abort cleanly: "nothing to re-frame — run knowledge-setup (without --reframe) to bootstrap this base first." When it exists, read it, validate its knowledge_slug matches --knowledge-slug (mismatch → abort), then jump straight to Step 2.5 — skip the wiki pre-flight / dispatch (Steps 2/3) and the init call (Step 4); the wiki and binding already exist, so re-frame only rewrites the charter via set-charter.Check <knowledge_root>/.cogni-wiki/config.json:
If <knowledge_root> exists but contains foreign files (no .cogni-wiki/, but non-empty subdirs that are not the standard cogni-wiki layout — raw/, wiki/, assets/), abort: "path exists but is not a wiki — choose a different --knowledge-root or move the existing files."
This step steers the base: it captures a coarse charter (what the base is about, who reads it, where its boundaries are, which themes to cover first) and the default market + output_language, in one coherent interview rather than two disjoint prompts. The charter is the base-level analog of knowledge-plan's per-question topic-framing (references/topic-framing.md); the full base-scoped playbook + question bank lives in ${CLAUDE_PLUGIN_ROOT}/references/charter-framing.md. Read it once here.
Why a charter: in cogni-knowledge one base accumulates many topics over time, so the base needs a coarser charter while each knowledge-plan run keeps the finer per-question framing that already exists. The charter is persisted to binding.json::charter (schema 0.1.4) and seed themes to topic_lineage.open_themes[]; knowledge-plan Step 0.4 then inherits the charter as grounding so every future run is anchored to the base's domain.
Engage / skip (mirror topic-framing's contract — this base must be steered, so default-on with an explicit opt-out):
--no-charter is passed, or the run is non-interactive (all of --charter-domain/--charter-audience/--charter-scope supplied via flags). In the skip case, charter fields fall through to their flags (else "") and open_themes[] to --open-themes (else []) — still a complete schema-0.1.4 binding.--reframe mode — re-steer an existing charter. When invoked with --reframe, this same interview runs against the existing binding instead of a fresh one:
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/knowledge-binding.py read --knowledge-root <knowledge_root>
Pull binding.charter.{domain,audience,scope} and binding.topic_lineage.open_themes[].<domain>" so an unchanged field is one keystroke to keep).set-charter union-merges --open-themes into the existing backlog (it appends; it never clobbers or removes). Dropping a seed theme stays a hand-edit for now.--reframe mode (those live in research_defaults, not the charter; re-framing steers domain/audience/scope/themes only). Skip straight to writing the charter in Step 4's --reframe branch.When engaged, run the four framing moves (port the shape from references/charter-framing.md):
Glob the top-level shape, Read the manifest/README, sample 2–3 files; cap ~50 KB). No network here; no writes.--no-prelim-search was passed, issue 2–3 broad WebSearch queries on the domain to ground the seed-theme suggestions; review the top snippets for the dominant themes/organizations/terminology. Any error → skip silently and fall through to pure reasoning. The scan never blocks framing.AskUserQuestion turn (call ToolSearch(query="select:AskUserQuestion") to load the schema if needed), ≤4 skippable, base-scoped questions. Fold the market/language questions into this same turn (or a single immediate follow-up turn if the four-question budget is full):
charter.domain)charter-framing.md → charter.audience)charter.scope)open_themes[])--market not passed): the supported codes; default dach (Recommended).--output-language not passed): option 1 is the market's default_output_language (Recommended), option 2 en, plus 1–2 common others; "Other" takes a two-letter code.
Every question is skippable — "I'll decide later" drops to the safe default (charter field → "", market → dach, language → the market's default_output_language, no seed themes).Resolve the market / language default exactly as before (the precedence and helper are unchanged):
--market and --output-language were passed, use them as-is.knowledge-plan uses for candidate_domains):
python3 "${WORKSPACE_PLUGIN_ROOT:-$(ls -td "$HOME"/.claude/plugins/cache/insight-wave/cogni-workspace/*/ | head -1)}/scripts/get-market-config.py" --plugin research --market <market-or-default-dach>
Read data.default_output_language from the envelope (e.g. dach→de, fr→fr, eu→en).dach, language = market's default_output_language).Carry the resolved charter.{domain,audience,scope}, open_themes[], market, and output_language into Step 4.
Writer-quality knobs (prose_density, tone, citation_format, target_words) are flag-or-default — NOT prompted here. Each has a safe default and is primarily a per-run choice on knowledge-plan, so the interview stays scoped to charter + market/language; the four knobs persist from their flags when passed, else the script-side defaults (executive/objective/ieee/2000). Overridable per run via knowledge-plan --prose-density|--tone|--citation-format|--target-words. Carry any passed flags into Step 4.
cogni-knowledge owns the wiki skeleton natively — it does not dispatch cogni-wiki:wiki-setup. The wiki engine is vendored under scripts/vendor/cogni-wiki/; the only residue a fresh wiki needs before Step 3.5's curated re-seeding is the directory skeleton plus an initial .cogni-wiki/config.json (Step 3.5 then bumps its schema_version 0.0.7 → 0.0.9 via the vendored config_bump.py, which requires the file to already exist).
Create the skeleton and write the config natively. Pass the title/description/url as environment variables to python3 -c so an arbitrary <knowledge-title> containing $, a backtick, or a quote can never break the JSON or expand in the shell:
mkdir -p <knowledge_root>/raw <knowledge_root>/assets <knowledge_root>/.cogni-wiki \
<knowledge_root>/wiki/concepts <knowledge_root>/wiki/entities <knowledge_root>/wiki/people \
<knowledge_root>/wiki/sources <knowledge_root>/wiki/questions <knowledge_root>/wiki/syntheses \
<knowledge_root>/wiki/interviews <knowledge_root>/wiki/audits || abort "wiki skeleton mkdir failed"
WIKI_NAME='<knowledge-title>' WIKI_SLUG='<knowledge-slug>' \
WIKI_DESC='<description, or empty>' WIKI_PUB='<publisher-base-url, or empty>' \
WIKI_ROOT='<knowledge_root>' python3 -c '
import json, os, datetime
cfg = {
"name": os.environ["WIKI_NAME"],
"slug": os.environ["WIKI_SLUG"],
"description": os.environ.get("WIKI_DESC", ""),
"created": datetime.date.today().isoformat(),
"entries_count": 0,
"last_lint": None,
"schema_version": "0.0.7",
}
pub = os.environ.get("WIKI_PUB", "")
if pub:
cfg["publisher_base_url"] = pub
with open(os.path.join(os.environ["WIKI_ROOT"], ".cogni-wiki", "config.json"), "w") as fh:
json.dump(cfg, fh, indent=2)
' || abort "wiki config.json write failed"
On a mkdir / config.json failure, surface the error verbatim and stop. The binding is not written if the wiki skeleton was not created.
Run this step only on the fresh-wiki branch — when Step 3 just scaffolded
the wiki skeleton. Skip it when Step 2 re-used an existing wiki, and in
--reframe mode (which already skips Steps 2–3). It turns the
schema_version 0.0.9 layout the contract below declares into the actual seeded
shape, so a NEW wiki opens with a curated MAP front door (wiki/index.md)
over its per-type sub-indexes — with the overview narrative folded into the
wiki/index.md intro (where knowledge-finalize maintains it via
overview_update.py narrative-splice --target-file index.md) and wiki/overview.md
reduced to a stub holding the ## Recent syntheses list — rather than leaving the
wiki root files unstructured. All edits are CK-side; the vendored engine scripts are read-only — this
step calls them, never edits them.
Resolve the wiki-ingest scripts dir (Step 3 dispatches the skill but resolves
no script dir, so resolve it here, mirroring knowledge-finalize Step 0):
. "${CLAUDE_PLUGIN_ROOT}/scripts/resolve-wiki-scripts.sh"
WIKI_INGEST_SCRIPTS=$(resolve_wiki_scripts wiki-ingest config_bump.py) \
|| abort "cogni-wiki wiki-ingest scripts not found"
(a) Seed the six per-type sub-index stubs via the canonical renderer. Call
sub_index.py render per type — it writes each wiki/<type>/index.md with its
<!-- MACHINE-OWNED:<TYPE>-INDEX --> ownership marker under the wiki lock, so the
renderer treats it as a machine-owned upsert target on the first
knowledge-finalize. Do not hand-author the markers — that would duplicate
sub_index.py's logic, which the no-duplicate-upstream-logic convention forbids:
for t in concepts entities people sources questions syntheses; do
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/sub_index.py" render \
--type "$t" --wiki-root <knowledge_root> \
--wiki-scripts-dir "$WIKI_INGEST_SCRIPTS" \
|| abort "sub_index render failed for $t"
done
(b) Seed the curated root files — wiki/index.md (curated MAP front door,
overview narrative in its intro), wiki/overview.md (stub), and the
knowledge-native SCHEMA.md. Seed all three curated root files via Bash
heredocs (since this skill's allowed-tools carries no Write tool — the seed
mechanism is cat > … <<'EOF', not a Write call). All bodies use a quoted
heredoc delimiter (<<'EOF') — they need no shell expansion, and quoting keeps a
<knowledge-title> that happens to contain a $ or backtick from being expanded
or executed. Substitute <knowledge-title> and — on the _Created: subtitle
line only — today's date YYYY-MM-DD textually before running (the
quoted delimiter means the shell will not expand a $(date) here — the log
heredoc in (c) is the one place that stays unquoted precisely because it does
rely on $(date)). Never replace-all on YYYY-MM-DD: the SCHEMA.md seed's
audits/ tree line carries lint-YYYY-MM-DD.md / health-YYYY-MM-DD.md as
filename patterns that must stay literal. The in-body <knowledge-root>/
tree root in the SCHEMA.md seed likewise stays literal — it is a generic
placeholder in the deposited contract, not a substitution token:
wiki/index.md becomes the curated portal front door carrying the
MACHINE-OWNED:OVERVIEW-NARRATIVE block in its intro (the narrative now
lives here, not in wiki/overview.md) plus the MACHINE-OWNED:ROOT-INDEX
ownership marker and the curated-map intro line. knowledge-finalize's
root_index.py render upserts one ## <theme> section per theme as research
lands (each a count-link to its per-type sub-indexes, no per-page bullets), and
overview_update.py narrative-splice --target-file index.md refreshes the
OVERVIEW-NARRATIVE inner. The seed carries no ## <theme> sections yet (none
exist) and no per-page bullet line, so the vendored strip_seed_placeholder
has nothing to strip. The intro line matches root_index.py's so the first
finalize render is a no-op on the intro.wiki/overview.md is re-seeded as a thin stub that points at the
curated map: it no longer carries the OVERVIEW-NARRATIVE block (that moved to
index.md's intro). It remains the home of the ## Recent syntheses running
list that knowledge-finalize's overview_update.py recent-bullet appends —
the only surface still written there.SCHEMA.md (at the wiki ROOT, <knowledge_root>/SCHEMA.md — one level
above the wiki/ page tree the two seeds above target; that is where
wiki-setup copies its generic template) is replaced with the
knowledge-native contract: the generic template declares directories the
knowledge pipeline never writes (decisions/, meetings/, notes/) while
omitting the knowledge-native surfaces (sources/, questions/, people/,
interviews/, audits/) — so without this overwrite every new base violates
its own self-describing contract. The seed's directory set is pinned to the
sub_index.py REGISTRY's six indexed types plus the on-disk
interviews/ / audits/ / wiki/meta/, and it documents the
concept-vs-entity instance-free test (the same rule the
concept-distiller agent applies) so the contract is readable from inside
the base. This seed is also the canonical copy knowledge-index's schema
truth-up applies to existing bases — change it here, never fork it there.Seed the three curated root files by running the verbatim three-heredoc block in ${CLAUDE_PLUGIN_ROOT}/references/curated-layout-seed.md §"Seed payload (run verbatim)" — apply the <knowledge-title> / date substitutions described above before running. The three cat > … <<'EOF' seeds are wiki/index.md (curated MAP front door, MACHINE-OWNED:OVERVIEW-NARRATIVE + MACHINE-OWNED:ROOT-INDEX), wiki/overview.md (stub), and <knowledge_root>/SCHEMA.md (the knowledge-native contract).
(c) Move the control log under wiki/meta/. Create the meta dir and seed
wiki/meta/log.md directly — not via control-path.py log: the direct
write keeps the seed self-contained (no resolver round-trip), and the resolver
now defaults a file absent from both layouts to wiki/meta/ anyway, so the
direct seed and the canonical resolution agree.
_knowledge_lib.meta_dir(<knowledge_root>) is definitionally
<knowledge_root>/wiki/meta. This heredoc alone uses an unquoted delimiter
(<<EOF) so the shell expands $(date +%Y-%m-%d) into the log line:
mkdir -p <knowledge_root>/wiki/meta
cat > <knowledge_root>/wiki/meta/log.md <<EOF
# Log
Append-only record of every wiki + knowledge operation. Never rewritten.
## [$(date +%Y-%m-%d)] setup | wiki initialized
EOF
(d) Drop the folded-away flat control file. Remove only the flat wiki/log.md
wiki-setup seeded — its content now lives at wiki/meta/log.md (seeded in (c)).
Keep wiki/overview.md — it is the stub re-seeded in (b) that holds the
## Recent syntheses list knowledge-finalize appends to via overview_update.py recent-bullet; deleting it would make the first finalize recreate a bare default:
rm -f <knowledge_root>/wiki/log.md
(e) Advertise schema_version 0.0.9. The Step 3 scaffold writes 0.0.7; bump it via
the locked config_bump.py (the scaffold has no schema flag of its own):
python3 "$WIKI_INGEST_SCRIPTS/config_bump.py" \
--wiki-root <knowledge_root> --key schema_version --set-string 0.0.9
After this step a fresh wiki has exactly wiki/index.md (the curated MAP front
door, overview narrative in its intro), wiki/overview.md (the seeded stub holding
the ## Recent syntheses list), wiki/meta/log.md, and the six per-type
wiki/<type>/index.md stubs — no flat wiki/log.md. This invariant holds
across the first knowledge-finalize: finalize folds the overview narrative
into the index.md intro via overview_update.py narrative-splice --target-file index.md and re-renders the curated root MAP (root_index.py), never regrowing a
competing root file. knowledge-health's assertions for this shape
are a separate follow-up child of the epic — this step seeds the layout the check
will later assert; it does not add health expectations.
--reframe mode → set-charter (in-place, partial). Skip the init call entirely. Write only the charter fields the user actually changed in Step 2.5, passing only those flags (an unchanged field is simply omitted — set-charter leaves it untouched; framed_at is re-stamped only when domain/audience/scope changes; --open-themes union-merges into the existing backlog):
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/knowledge-binding.py set-charter \
--knowledge-root <knowledge_root> --knowledge-slug <knowledge_slug> \
[--charter-domain "<new domain>"] [--charter-audience "<new audience>"] \
[--charter-scope "<new scope>"] [--open-themes "<theme1|theme2|...>"]
set-charter writes the same schema-0.1.4 charter shape init does (it is a new action, not a new field — schema_version is not bumped) and is fail-soft on a pre-0.1.4 binding (it recreates a complete charter block). On success: false (e.g. nothing-to-update, or a --knowledge-slug mismatch), surface the error and stop. Then go to Step 5's --reframe branch (print the updated-charter summary; skip the first-question on-ramp).
Normal (bootstrap) mode → init:
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/knowledge-binding.py init \
--knowledge-root <knowledge_root> \
--knowledge-slug <knowledge_slug> \
--knowledge-title "<knowledge_title>" \
--wiki-path <knowledge_root> \
--market <resolved market> \
--output-language <resolved output_language> \
[--prose-density <flag>] [--tone <flag>] [--citation-format <flag>] [--target-words <flag>] \
[--charter-domain "<resolved domain>"] [--charter-audience "<resolved audience>"] \
[--charter-scope "<resolved scope>"] [--open-themes "<theme1|theme2|...>"]
--market / --output-language carry the Step 2.5 resolution into binding.json::research_defaults (schema 0.1.2). The four charter args carry the Step 2.5 charter interview into binding.json::charter + topic_lineage.open_themes[] (schema 0.1.4) — pass each only when resolved (a skipped/blank charter field simply omits the flag and falls through script-side to ""; framed_at is stamped only when any charter field is non-empty). The four writer-quality flags are likewise passed only when the user supplied them; omitted flags fall back script-side to the DEFAULT_RESEARCH_DEFAULTS block (dach/en/executive/objective/ieee/2000), so a plain init still writes a complete schema-0.1.4 binding (research_defaults complete, charter all-"", open_themes []). The script returns the standard {success, data, error} envelope. On failure (e.g. binding already exists), surface the error. The script refuses to overwrite an existing binding — Step 1's pre-flight should have caught that, but the script is the second line of defence.
--reframe mode → updated-charter summary, no on-ramp. Print a short confirmation of the re-framed charter (domain / audience / scope, and any seed themes added) and stop. Do not run the first-question on-ramp — a base being re-framed already has projects, so the right next step is knowledge-resume --knowledge-slug <slug> (to see where it stands) or knowledge-plan --knowledge-slug <slug> --topic '...' (to frame the next research question against the freshened charter), not a first-question chain. Point at those and end the run.
Normal (bootstrap) mode — the rest of this step.
First print a short summary, ≤ 8 lines:
<knowledge_root> — they are the same in the default layout)<knowledge_root>/.cogni-knowledge/binding.json)<charter.domain>, audience <charter.audience>, scope <charter.scope><resolved market>, output language <resolved output_language>, density <prose_density>, tone <tone>, citations <citation_format>, target <target_words>w (all inherited by knowledge-plan; overridable per run)Do not print the full binding JSON in the summary — point at the file path and let the user inspect it if they want.
Then the first-question on-ramp. A fresh base is empty — the value of setup is leaving the user with a framed first research question, not just a binding. Replace the old static "suggested next action" line with one interactive prompt:
--no-charter (flag-only) run — print the static guidance instead (the bullet below) and stop. Automation-safe: setup never blocks waiting for input it can't get.AskUserQuestion: "Frame your first research question now?". When open_themes[] is non-empty, surface the seed themes as the selectable options so the user picks which one to frame first (single select; default = the first seed theme); always include a "No — pick later" option.
Skill("cogni-knowledge:knowledge-plan",
args="--knowledge-slug <slug> --topic '<chosen seed theme>' --frame")
--frame forces knowledge-plan's Step 0.4 per-question topic-framing (which now inherits this base's charter as grounding), so the user leaves with a sharpened first question + plan.json + .metadata/framing.md. The chain stops at plan — knowledge-curate → knowledge-fetch → … each cost web/tokens, so they stay the user's explicit per-run decision. Do not auto-run any phase past plan.open_themes[] as the candidate menu.Static next-action guidance (printed on skip / "pick later"):
Next:
cogni-knowledge:knowledge-plan --knowledge-slug <slug> --topic '<one of your seed themes>', thenknowledge-curate→knowledge-fetch→knowledge-ingest→knowledge-compose→knowledge-verify→knowledge-finalize. Seed themes for this base:<open_themes joined by ', '>(or "none — pick any topic" when empty).
wiki_path; the wiki's own slug is read live from <wiki_path>/.cogni-wiki/config.json whenever a consumer needs it, so a wiki rename never causes the binding to drift.--knowledge-slug collides with a sibling directory. Step 1's binding-existence check protects against double-init; if the sibling is a non-wiki directory, Step 2's foreign-files check fires.mkdir / config.json write); the user can re-run after fixing it.cogni-wiki:wiki-ingest's job (transitively via knowledge-ingest).cogni-wiki:wiki-prefill).knowledge-plan, where the topic is known.market/output_language + the four writer-quality knobs prose_density/tone/citation_format/target_words) in binding.json::research_defaults (Step 2.5, schema 0.1.2). The per-run choice still lives in knowledge-plan — a single plan can override any base default with its own matching flag (e.g. an English report about a German market, or an executive-density draft on a standard-default base).knowledge-plan) and is NOT a per-question prompt: the finer per-research-question framing remains knowledge-plan Step 0.4's job, which inherits this charter as grounding.plan. The Step 5 on-ramp chains at most into knowledge-plan --frame (cheap, no-web decomposition); knowledge-curate onward stay the user's cost-bearing per-run decision.--reframe re-steers the charter only (domain / audience / scope / additional seed themes), in place via set-charter. It does NOT re-run wiki setup, does NOT re-run init, does NOT re-resolve market/output_language (those live in research_defaults, untouched), and does NOT run the first-question on-ramp. It only ADDS seed themes (union-merge) — removing or replacing a seed theme stays a hand-edit. The charter's data shape (schema 0.1.4) is unchanged.<knowledge_root>/ containing:
.cogni-wiki/config.json (written natively by Step 3).cogni-knowledge/binding.json (from knowledge-binding.py init)raw/, assets/, and the curated wiki/ output layout below.No files are written outside <knowledge_root>/.
schema_version 0.0.9)The inverted pipeline deposits its knowledge into wiki/ as a curated,
progressively-disclosed tree — a single front door over per-type sub-indexes,
not a flat dump:
wiki/
├── index.md ← curated MAP front door (root_index.py): the overview
│ narrative (MACHINE-OWNED:OVERVIEW-NARRATIVE) in its
│ intro, then one `## <theme>` section per theme, each a
│ count-link to the sub-indexes below — no per-page bullets.
├── overview.md ← stub: points at index.md; holds the `## Recent
│ syntheses` list (overview_update.py recent-bullet).
├── concepts/index.md ← per-type sub-index (exists today via concepts_index.py)
├── sources/index.md ┐
├── questions/index.md │
├── syntheses/index.md │ per-type machine-owned sub-indexes
├── entities/index.md │
├── people/index.md ┘
└── meta/ ← visible control files: log.md, context_brief.md,
open_questions.md
schema_version 0.0.9 is additive and read-forward. It adds the
first-class person page type (wiki/people/, split
out of the catch-all entity) to the curated layout the previous bump
declared, on top of the existing per-type-directory contract. As with the 0.0.6 (sources/), 0.0.7 (questions/), and 0.0.8
(curated layout) bumps, an older-but-post-migration wiki reads forward without
a rewrite — an absent wiki/people/ directory on a 0.0.8 base is harmless;
0.0.5 remains the hard-fail boundary (pre-migration wikis still abort). This is the wiki schema_version, distinct
from the cogni-knowledge plugin version.
Layout seeding for NEW wikis lands here (Step 3.5 above) — a fresh wiki opens
in this curated shape (wiki/index.md curated MAP front door with the overview
narrative in its intro, wiki/overview.md stub, wiki/meta/log.md, per-type
sub-index stubs, schema_version 0.0.9). The wiki/meta/ control-file path centralization
(flipping the canonical write target, with a legacy fallback) and the
lint/health enforcement of the exemption below remain follow-up children of
this epic. Until the path centralization lands, the legacy flat paths
wiki/context_brief.md and wiki/open_questions.md remain valid; wiki/meta/ is
the seeded home for log.md and the declared target the rest of the layout
work builds toward.
Overview ownership (landed). The overview narrative is folded into the
wiki/index.md intro (the MACHINE-OWNED:OVERVIEW-NARRATIVE block lives there).
knowledge-finalize maintains it via overview_update.py narrative-splice --target-file index.md and re-renders the curated root MAP (root_index.py), so
the seeded shape survives the first finalize byte-for-byte (the seeded intro line
matches root_index.py's, so the first render is a no-op on the intro). So
seeding (Step 3.5) seeds the folded shape directly: wiki/index.md carries the
OVERVIEW-NARRATIVE block + the ROOT-INDEX marker, and wiki/overview.md is a
stub holding only the ## Recent syntheses list. The vendored wiki_index_update.py
stays byte-identical — root_index.py is a new CK-side script (Option A).
Per-type index.md is a machine-owned sub-index, not a page. Each
wiki/<type>/index.md is generated, not authored, so it is exempt from the
entries_count, orphan_page, and reverse_link_missing checks — the same
structural exemption the lint/health tooling already grants is_audit_slug
pages (lint-* / health-*). Declaring the exemption here gives the
lint/health-enforcement follow-up a contract to point at.
${CLAUDE_PLUGIN_ROOT}/references/delegation-contract.md — what this skill owns vs. delegates (incl. §"How Skill(...) blocks are written")${CLAUDE_PLUGIN_ROOT}/references/differentiation-thesis.md — why wiki-first${CLAUDE_PLUGIN_ROOT}/scripts/vendor/cogni-wiki/ — the vendored wiki engine Step 3.5 calls (config_bump.py, sub_index.py)${CLAUDE_PLUGIN_ROOT}/scripts/knowledge-binding.py --helpnpx claudepluginhub cogni-work/insight-wave --plugin cogni-knowledgeAsk a question against a bound cogni-knowledge base — resolve its wiki path from binding.json, rank and read the covering pages, and synthesize a cited answer natively. The shallow rung of the query↔research ladder: one question, index-first read of ≤12 pages, no web, no verify; read-only by default, opt-in `--file-back` deposits an un-verified synthesis page. Use when the user says 'query my <slug> knowledge base', 'ask the <slug> base about X', or 'knowledge-query <slug> [--file-back]'.
Sets up and maintains a persistent Obsidian wiki vault for cross-project knowledge management. Scaffolds structure, manages hot cache, and routes to sub-skills.
Build and maintain an LLM-curated personal knowledge base — the "LLM Wiki" pattern from Andrej Karpathy's April 2026 gist. Use this skill whenever the user wants to ingest a source (paper, article, transcript, PDF, notes) into a persistent compounding knowledge base, ask a question against accumulated notes, lint or audit such a base, or initialize a new one. Trigger on phrases like "add this to my wiki", "ingest this paper", "compile this into the knowledge base", "what does my wiki say about X", "lint the wiki", "build a knowledge base from these documents", "research notes", "second brain", "personal knowledge base", or any reference to LLM Wiki / OmegaWiki. Trigger even when the user does not say "wiki" — if they are accumulating sources over time and want them organized, this applies. The skill scales — sharded indexes, atomic pages, YAML frontmatter, and a bundled search script keep the wiki from becoming a context bottleneck at hundreds or thousands of pages.