# llm-wiki-kit Manual

`llm-wiki-kit` is a hook-first runtime that keeps a project-local living Markdown wiki while users work normally in Codex, Claude Code, or opencode.

The core rule is answer-first operation. Users should not need to remember a separate `record`, `ingest`, or maintenance command loop. Hooks inject useful context, store redacted operational evidence, and help the active agent move durable knowledge into `llm-wiki/` when it matters.

## Language Behavior

The runtime supports seamless Korean/English use:

- If the current user prompt is clearly Korean, hook-visible guidance is Korean.
- If the current user prompt is clearly English, hook-visible guidance is English.
- Codex synthetic plan execution prompts — specifically the exact phrase `Implement the plan.` — are not treated as English; they reuse the last real session language or project preference.
- A project can set `preferredLanguage` in `llm-wiki/.kit-state.json` for neutral prompts.
- When there is no clear prompt language, Claude Code may use its `settings.json` `language` value when present.
- If no setting exists, the runtime checks local `CLAUDE.md` and `AGENTS.md` language signals.
- The fallback is English.
- Commands, paths, code identifiers, package names, API names, logs, and original error text are kept unchanged.

This is intentionally instruction-driven for both Codex and Claude Code. Claude Code may expose a language setting in some versions, but the kit does not depend on that setting being present.

## Mental Model

The wiki has three layers:

```text
raw evidence -> curated wiki -> rules and retrieval
```

- `raw/`: immutable or redacted evidence. Default hooks store small redacted event envelopes, not full transcripts.
- `wiki/`: curated project knowledge maintained by the agent.
- `outputs/`: live Q&A chunks, reports, and maintenance candidates.
- `AGENTS.md`, `CLAUDE.md`, and `.kit/procedures/`: instructions and operating rules for agents (kit-managed; do not edit). `procedures/`: user-authored runbooks (`type: procedure`, first-class wiki pages).

Chat history is temporary. Durable project knowledge belongs in repository Markdown so it survives new sessions, compaction, and different agents.

## Created Structure

Bootstrap or install creates:

```text
llm-wiki/
├── .kit-state.json
├── raw/
├── wiki/
│   ├── index.md
│   ├── memory.md
│   ├── log.md
│   ├── sources/
│   ├── concepts/
│   ├── decisions/
│   ├── architecture/
│   ├── debugging/
│   ├── context/
│   └── queries/
├── outputs/
│   ├── questions/
│   ├── reports/
│   ├── exports/
│   └── maintenance/
├── evals/
└── procedures/
```

`wiki/memory.md` is the short hot index used in hook context. `wiki/index.md` is the navigation map. General source material belongs in `raw/sources/`; maintenance migrates known legacy layout into the current taxonomy, including `raw/inbox/`, `raw/assets/`, top-level `sources/`, top-level `templates/`, and `wiki/entities/`. `.kit-state.json` records which runtime last applied managed templates. Runtime updates do not overwrite curated project knowledge.

## Normal Use

Use Codex, Claude Code, or opencode normally. Installed hooks:

- inject functional compact context at session start, instructions loaded, and prompt submit;
- select Korean or English hook guidance from the current real user prompt, remembered session language, project preference, and local instruction files;
- use `wiki/memory.md`, `wiki/index.md`, relevant wiki search, maintenance signals, update notices, and compact recovery packets;
- record redacted prompt/tool/result summaries in per-turn state;
- preserve safe evidence pointers as `evidence_refs` when changed files or verification commands are available;
- archive only handoff-worthy durable checkpoints into chunked `outputs/questions/YYYY-MM-DD/live-qa-001.md` files;
- avoid automatic `wiki/queries/` and `wiki/decisions/` promotion in the default answer-first mode;
- queue durable cleanup candidates for explicit documentation requests, structured durable conclusions, or queue-worthy recovered stale turn state that were not reflected in durable wiki/procedure files;
- report queue pressure at session start without applying lifecycle mutations; stale-item skipping, reviewed-item archival, and layout cleanup run only through explicit maintenance commands;
- report stale managed rules/templates at session start without rewriting project files; refresh them only through explicit install, update, or post-update commands;
- report legacy Codex-facing `oh-my-codex:wiki`/`omx_wiki` surfaces for explicit cleanup instead of removing them during routine hooks.

If wiki maintenance delays the actual answer, the workflow is being used wrong. The current user request comes first.

## Capture Mode

The kit uses the answer-first capture mode. Hooks keep simple Q&A, status checks, keyword-only replies, and ordinary tool-heavy work out of durable wiki and live Q&A by default. They archive explicit durable requests, structured `Decision:`/`Policy:`/`Procedure:` conclusions, structured debugging conclusions such as `Root cause:` only when verification or changed-file evidence exists, and detected durable wiki/procedure updates. Explicit durable requests and structured durable conclusions create maintenance queue candidates only when no durable wiki/procedure update is detected.

Korean and English explicit-durable detection are intentionally **asymmetric**, not parallel. English forms require an object (`remember this`, `record the decision`, `document this`); Korean action verbs (`추가해`/`정리해`/`남겨둬`/`기억해`/`메모해`/`기록해`) are treated as explicit durable requests only when a wiki/document/page/memory context token (`위키`/`wiki`/`문서`/`페이지`/`메모리`) or a `...로 만들어`/`문서화` form accompanies them, so ordinary work requests like `이 기능 추가해줘` or `코드 정리해줘` stay transient. The `문서화`/`문서화해` form is self-gating (it carries the documentation context itself) and therefore matches without a separate context token; this is a deliberate divergence from the English `document` verb, which still requires an object. Edge-case forms are not guaranteed to be symmetric across the two languages. Short Korean requests are not dropped by the char floor as long as they contain at least three Hangul syllables. Only Korean and English are supported; prompts in other CJK scripts (Japanese/Chinese, which contain no Hangul) fall back to English by design, with no warning.

## Install

Linux/macOS:

```bash
npm install -g llm-wiki-kit@latest
llm-wiki install --workspace /path/to/project --profile standard
llm-wiki doctor --workspace /path/to/project
```

Use `sudo npm install -g llm-wiki-kit@latest` only when the global npm prefix is root-owned. Run `llm-wiki install` as the user who owns the Codex/Claude settings.

`llm-wiki install` also syncs bundled Codex and Claude Code skills named `llm-wiki-*` into `$CODEX_HOME/skills` or `~/.codex/skills`, and into `~/.claude/skills`. It installs missing skills and updates only skills that were previously managed by the kit and not locally edited. Existing user-created skills with the same name are preserved, except obsolete public llm-wiki skills that the kit removes from active provider skill roots. Use `--no-codex` to skip Codex hooks and skills, `--no-claude` to skip Claude hooks and skills, and `--no-skills` when you intentionally want hook installation without writing either skill root.

Native Windows:

```powershell
npm install -g llm-wiki-kit@latest
llm-wiki install --workspace C:\path\to\project --profile standard
llm-wiki doctor --workspace C:\path\to\project
```

Windows uses npm's `llm-wiki.cmd` shim. The installer writes Codex `commandWindows` hooks and Claude Code Windows-safe `node.exe <bin>` commands. Restart Codex and Claude Code after installing or updating hooks.

Source checkout development:

```bash
npm install
./install.sh --workspace /path/to/project --profile standard
node --test
```

Pre-publish smoke:

```bash
candidate_dir="$(mktemp -d)"
npm pack --json --pack-destination "$candidate_dir"
smoke_root="$(mktemp -d)"
HOME="$smoke_root/home" NPM_CONFIG_CACHE="$smoke_root/npm-cache" NPM_CONFIG_USERCONFIG="$smoke_root/isolated.npmrc" npm install --prefix "$smoke_root/prefix" --ignore-scripts "$candidate_dir/llm-wiki-kit-<version>.tgz"
HOME="$smoke_root/home" XDG_DATA_HOME="$smoke_root/data" CODEX_HOME="$smoke_root/codex" node "$smoke_root/prefix/node_modules/llm-wiki-kit/bin/llm-wiki.js" install --workspace "$smoke_root/project" --profile standard --json
```

This candidate check must not use `npm install -g` or a real project/provider home. The complete release gate below verifies the same exact tarball on isolated Linux and native Windows.

## Commands

Most users should not need these during daily coding. They are for install, update, diagnostics, and agent-side maintenance.

- `llm-wiki manual`: print this manual.
- `llm-wiki install --workspace <project> --profile standard [--no-codex] [--no-claude] [--no-opencode] [--no-skills]`: install hooks, sync bundled Codex and Claude Code skills, and bootstrap the workspace.
- `llm-wiki update --check --workspace <project> [--to <version-or-tag>]`: check npm without changing files.
- `llm-wiki update --workspace <project-or-search-root>`: update the global runtime when npm has a newer target, then reapply hooks and managed templates.
- `llm-wiki post-update --workspace <project> [--all] [--no-codex] [--no-claude] [--no-opencode] [--no-skills]`: reapply hooks, bundled skills, and managed templates without running npm install.
- `llm-wiki projects --workspace <search-root>`: list known/discovered project roots and update commands.
- `llm-wiki status --workspace <project>`: offline consistency report.
- `llm-wiki version`: print the installed runtime version.
- `llm-wiki doctor --workspace <project>`: installation and hook roundtrip diagnostics.
- `llm-wiki bootstrap --workspace <project>`: create project-local wiki structure.
- `llm-wiki migrate --workspace <project>`: copy legacy wiki material into the current layout.
- `llm-wiki search "<query>" --workspace <project> [--limit 5] [--explain] [--no-expand] [--include-episodic] [--include-archived] [--all-projects] [--show-filtered] [--json]`: the agent-facing search surface. Hits carry a `wiki/path.md#section` ref plus a file-accurate `L<start>-L<end>` line range, so an agent can read just the matched section with its native Read tool instead of the whole page. Single short body-only matches are dropped as retrieval noise by default; the suppression count appears in the no-match outcome, `--show-filtered` lists what was dropped, and `LLM_WIKI_KIT_SEARCH_FILTER=0` disables the filter. A no-match result exits 0 with an explicit outcome line: retry once with the suggested vocabulary (copy-pasteable command included), then state that the wiki has no record and answer normally. `--json` emits a versioned `llm-wiki-search/1` schema with redacted hits.
- `llm-wiki context "<query>" --workspace <project> [--all-projects]`: verbose debug view of hook context sources; add `--compact --max-context-chars <n>` to preview hook-sized output.
- `llm-wiki memory [query] --workspace <project>`: review current hot memory, active wiki root, retrieval hits for an optional query, queue state, and health.
- `llm-wiki eval --workspace <project> [--fixture <path>] [--limit 5] [--json]`: run retrieval fixtures.
- `llm-wiki export --workspace <project> [--format all|llms|llms-full|json] [--output <dir>] [--dry-run] [--json]`: write durable wiki manifests.
- `llm-wiki lint --workspace <project> [<path>]`: wiki health check. With a `<path>` positional, scope the check to a single `wiki/` or `procedures/` page (page-local rules plus link resolution against the full corpus; corpus-global and graph-derived rules excluded). Add `--fail-on-warning` to fail on warnings as well as errors and `--suppress-auto-fixable` to hide frontmatter issues the next Stop hook auto-normalizes. The lint gate is **batched** by default: the kit counts durable `wiki/**`/`procedures/**` changes since the last corpus lint and prompts after N (default 10, via `lintBatchThreshold`); a corpus lint resets the counter, and the single-file form is an on-demand spot-check no longer required after every write. `--show-suppressed` re-shows issues dropped by a per-path exception annotated with the reason. Per-path exceptions live in `llm-wiki/.kit/lint-exceptions.json` (absent = none): each entry suppresses one lint code on a `paths` glob with a required `reason` and optional `expires`; secret-detection codes (`secret-like-content` family) demote to `warning` rather than silencing (also under global `lintSeverity: off`), and corpus-integrity codes cannot be excepted.
- `llm-wiki consolidate --workspace <project> [--dry-run]`: refresh generated blocks in `memory.md` and `index.md`.
- `llm-wiki maintenance --workspace <project> [--normalize-frontmatter [--dry-run] | --derive-tags [--dry-run] | --derive-keywords [--dry-run] | --generate-glossary [--dry-run] | --normalize-filenames [--apply | --dry-run] | --apply-lifecycle [--dry-run] | --fix-wikilinks [--write] | --approve <id> --target <wiki/...md> | --done <id> --target <wiki/...md> | --skip <id> [--note "..."]] [--json]`: show or update cleanup state, or explicitly normalize curated page metadata or filenames. `--derive-keywords` seeds `keywords:` from title/aliases/description/headings (Korean-aware stopword filter; mechanical — refine via the `llm-wiki-keywords` skill); `--generate-glossary` builds a category keyword map at `llm-wiki/.kit/keyword-glossary.json`.
- `llm-wiki archive-questions --workspace <project> [--date YYYY-MM-DD] [--dry-run]`: split old flat live Q&A files into chunks (a narrow subset of `maintenance --apply-lifecycle`; use standalone to avoid queue/layout side effects).
- `llm-wiki new <slug> --workspace <project> [--type <type>] [--title "<title>"] [--dir <wiki/...>] [--dry-run] [--json]`: scaffold a curated wiki page with a complete, lint-clean frontmatter stub (all required core fields plus `keywords`, `description`, `importance`, `confidence`, `last_verified`, `evidence_refs`). The slug picks the filename; `--type` (default `concept`) picks the directory and frontmatter `type`. Keywords are seeded from the title via the same derivation as `--derive-keywords`, so a fresh durable page does not immediately lint-error — refine them via the `llm-wiki-keywords` skill. `--dir` overrides the type→directory mapping. Use this to start a page so no required/recommended frontmatter field is missed.
- `llm-wiki fork --from <source-workspace> --to <target-workspace>`: copy durable wiki pages and stamp a `forked_from` block on each.
- `llm-wiki uninstall`: remove kit-managed hook entries, leaving project wiki contents intact.

## Update Flow

`llm-wiki update --check` contacts npm and reports an update only when the registry target is newer than the installed runtime.

`llm-wiki update`:

- runs `npm install -g llm-wiki-kit@<target>` only when needed;
- skips only npm install when the installed runtime already satisfies the target, then still runs `post-update`;
- checks that `npm root -g` points at the active runtime package root before installing;
- verifies that the active runtime and `post-update` runtime reached the registry target after installing;
- exits nonzero instead of printing `updated` when `npm install -g` succeeds but the active runtime is still old;
- reinstalls hooks without duplicating them;
- syncs bundled Codex and Claude Code skills through the same conservative managed-file policy;
- updates only managed project templates and policy blocks;
- preserves user-edited files and curated wiki contents;
- prints before/after runtime, registry target, npm global root, active runtime root, PATH command diagnostics, whether post-update ran, project-template changed/skipped/unchanged counts, and per-project detail lines;
- prints progress to stderr so JSON stdout remains parseable;
- supports `--timeout-ms` and `--max-dirs` for slow npm, WSL, or large search roots.

Installed npm runtimes also perform a cached hook-side update notice check. It never installs automatically. It only shows passive status in hook context when a newer npm release exists and the user is already working.

## Context And Search

Hook context is compact and function-focused. The agent-facing search surface is:

```bash
llm-wiki search "release verification" --workspace /path/to/project
llm-wiki search "release verification" --workspace /path/to/project --json
llm-wiki search "release verification" --workspace /path/to/project --limit 8 --explain
llm-wiki search "release verification" --workspace /path/to/project --all-projects
```

Each hit prints a section ref with a file-accurate line range (`wiki/path.md#section L12-L48`). Use the agent's native Read tool with that range instead of reading the whole page. When nothing matches, the command exits 0 and prints one outcome line: retry once using only the suggested vocabulary (a copy-pasteable `llm-wiki search "..."` command is included), then state that the wiki has no record and answer normally; further retries do not help. Single short body-only matches are noise-filtered before ranking and link expansion; the filter can be disabled per-invocation environment with `LLM_WIKI_KIT_SEARCH_FILTER=0` and inspected with `--show-filtered`.

The full debug form is:

```bash
llm-wiki context "auth architecture" --workspace /path/to/project
llm-wiki context "auth architecture" --workspace /path/to/project --json
llm-wiki context "auth architecture" --workspace /path/to/project --limit 8 --no-expand
llm-wiki context "auth architecture" --workspace /path/to/project --budget-chars 4000 --explain
llm-wiki context "auth architecture" --workspace /path/to/project --compact --max-context-chars 900
llm-wiki context "auth architecture" --workspace /path/to/project --show-hidden-reason
llm-wiki context "auth architecture" --workspace /path/to/project --include-episodic
llm-wiki context "auth architecture" --workspace /path/to/project --include-archived
```

Default search prioritizes durable semantic/procedural wiki pages. Episodic `wiki/queries/`, `wiki/context/`, and `session-log` pages are hidden unless promoted with durable metadata or explicitly requested. Archived and superseded pages are hidden unless `--include-archived` is used. Stale pages remain searchable with lower score. Wiki pages are indexed by Markdown section, while the result list remains page-compatible by keeping the best section hit per page. Korean (Hangul) content and queries are tokenized with character bi-grams so agglutinative no-space Korean compounds match across word breaks; other no-space scripts fall back to substring matching. JSON hits include `ref`, `heading`, `sectionOrdinal`, `rankReason`, `visibilityReason`, `evidenceRefs`, `matchedFields`, `scoreBreakdown`, `confidenceLevel`, `confidenceScore`, and `confidenceReasons`; the text formatter prints `why selected` for maintainers. `--budget-chars` caps returned hit snippets for reviewable context packs, and `--compact --max-context-chars <n>` previews the small hook formatter. `--show-hidden-reason` lists pages hidden by the visibility policy. Hook compact context uses shorter section refs and snippets, filters low-confidence hits in balanced prompts, and does not include debug lines.

Visibility note (footgun): `type: "context"` and `wiki/context/` pages are treated as episodic and are hidden from default search unless promoted — set `memory_type: "semantic"` (or `"procedural"`) together with `importance: 4` (or `5`) so the page counts as a promoted durable page, otherwise query it with `--include-episodic`. A `context` page that keeps the default `importance: 3` will not appear in hook context even if its body matches.

## Codex And Claude Code Skills

The package includes focused Codex and Claude Code skills for common wiki operations. The same bundled `llm-wiki-*` skill sources are installed into Codex's personal skill root and Claude Code's personal skill root:

- `llm-wiki-setup`: bootstrap, migrate, install, and doctor workflows.
- `llm-wiki-query`: answer natural-language read-only memory questions with existing wiki context before broad file search.
- `llm-wiki-lifecycle`: coordinate durable documentation, maintenance hygiene, and stale policy/document upgrade checks through internal document, maintain, and upgrade-docs modes.
- `llm-wiki-export`: run eval/export flows and produce durable handoff manifests.
- `llm-wiki-keywords`: refine and backfill wiki `keywords:` in batch by reading each document and writing search-optimized terms; clears `missing-keywords` (error, durable types), `recommended-keywords` (warning, every other curated type), `low-quality-keyword`, `keyword-drift`, and `mechanically-seeded-keyword` (warning, keywords auto-seeded by `--derive-keywords`/scaffold and not yet refined) lint findings. Durable page types (decision, architecture, procedure, concept, debugging) lint-error without keywords; every other curated type lint-warns. Core pages (index/memory/log) are exempt.

The user should not need to say `llm-wiki`, name a command, or choose a skill for the common paths. The agent should use `llm-wiki-query` behavior for "what do we know/remember/where is it?" questions. Explicit persistence requests, cleanup, queue review, archive, consolidate, lint/eval hygiene, and stale policy/document follow-through should route to `llm-wiki-lifecycle`. Requests to refine, extract, clean, or curate keywords (or fix wiki search quality) should route to `llm-wiki-keywords`. Lifecycle evaluates internal mode flags independently: durable persistence defaults to document+maintain, while upgrade-docs runs only on clear update, migration, lint, or old-policy signals.

Skill sync is conservative for existing users. Missing bundled skills are installed, kit-managed unmodified skills are updated, unmanaged same-name active skills are skipped, and locally edited managed active skills are preserved. Obsolete public llm-wiki skills are removed from active provider skill roots even when they were unmanaged or locally edited, because leaving them visible keeps a retired public surface active. `llm-wiki status` and `llm-wiki doctor` report whether bundled skills are current for Codex at `$CODEX_HOME/skills` or `~/.codex/skills`, and for Claude Code at `~/.claude/skills`; doctor warns if obsolete public skills remain.

## Memory Review

`llm-wiki memory` is a diagnostic view, not a new capture path:

```bash
llm-wiki memory --workspace /path/to/project
llm-wiki memory "auth architecture" --workspace /path/to/project
llm-wiki memory --workspace /path/to/project --section current
llm-wiki memory --workspace /path/to/project --section queue --json
llm-wiki memory --workspace /path/to/project --section health
```

It reports the active wiki root, warns when the supplied workspace looks like a nested `llm-wiki` directory, prints current `memory.md` focus bullets, shows retrieval hits for an optional query, summarizes the maintenance queue, and reports lint/eval health. It does not mutate wiki files. Queue changes still go through `llm-wiki maintenance`.

## Frontmatter, Evidence, Eval, And Export

Every curated wiki page is expected to carry `title`, `type`, `status`, `memory_type`, and `last_updated`. A missing required field is a lint warning (auto-filled on changed durable pages during maintenance); an invalid value (for example an unknown `type` or `status`) is a lint error. Optional standard fields use stable runtime defaults:

```yaml
description: "Short page purpose used by retrieval"
aliases:
  - "context ranking"
activation: "model_decision"
globs:
  - "src/wiki-*.js"
visibility: "default"
evidence_refs:
  - "file:src/wiki-search.js"
  - "cmd:node --test"
  - "raw:source-id"
  - "url:https://example.com/reference"
importance: 3
confidence: "medium"
last_verified: "unknown"
extensions:
  service_owner: "context-platform"
  rollout_enabled: true
```

Omitted defaults are `activation: model_decision`, `visibility: default`, `importance: 3`, `confidence: medium`, `last_verified: unknown`, and empty arrays. Project-specific typed metadata belongs under `extensions`, whose keys must use lowercase snake_case. Reserve `importance: 5` for a small set of pages that should consistently outrank peers.

A semantic edit to claims, decisions, procedures, or active guidance must update `last_updated` in the same change. Revise `last_verified`, `confidence`, `status`, and `evidence_refs` when the verification or evidence meaning changed. Formatting-only and metadata-normalization-only edits must not imply re-verification.

`activation` can be `always`, `model_decision`, or `manual`. `visibility` can be `default`, `private`, or `no-export`; private/no-export pages remain local but are excluded from generated exports. `llm-wiki lint` uses a structured YAML parser, rejects duplicate keys, aliases, and custom tags, and validates core fields, extensions, evidence safety, and reachability. `file:` must be repo-relative, `cmd:` must be a short single-line redacted-safe command, `raw:` should resolve to a raw/source candidate, and `url:` must be `http` or `https` without credentials. Reviewed high-importance durable pages should include `evidence_refs`.

`llm-wiki maintenance --workspace <project> --normalize-frontmatter --dry-run` previews explicit normalization without writing. Applying it merges legacy `source_id`, fills inferable core fields, removes redundant defaults, and moves unknown top-level fields under `extensions`. Collisions, invalid extension keys, and malformed YAML require manual review. UTF-8 BOM and Windows CRLF input are accepted. Hooks never normalize curated documents automatically.

`llm-wiki eval` reads `llm-wiki/evals/retrieval.json` by default:

```json
{
  "queries": [
    {
      "query": "semantic retrieval",
      "expected": ["wiki/architecture/retrieval.md"],
      "unexpected": ["wiki/queries/old-auto.md"]
    }
  ]
}
```

Missing or empty fixtures fail and exit nonzero. Present fixtures report expected recall, MRR, stale-hit rate, citation coverage, missed expected paths, unexpected hits, hidden unexpected paths, and top hits. Eval and export share the same durable visibility policy so archived/superseded/default episodic pages are treated consistently.

## Command Lifecycle

Every public and internal command is registered in `src/command-lifecycle.js` with its intended use: hook automatic, hook reminder, agent maintenance, user diagnostic, release-only, internal hook, or never hook. Hooks do not shell out to CLI commands; they share internal modules such as `buildContextPack`, `maintenanceSummary`, capture policy, and compact recovery. `llm-wiki status`, `llm-wiki doctor`, and tests report lifecycle registry issues so command/help/manual/test/hook policy drift is visible.

`llm-wiki export` writes `llms.txt`, `llms-full.txt`, and `llm-wiki.json` under `llm-wiki/outputs/exports/` by default. `llms.txt` is a curated onboarding and handoff manifest for agents and humans, not a passive SEO file. `llms-full.txt` is a bounded redacted context bundle for handoff or compaction recovery. `llm-wiki.json` is the structured manifest for future adapters and eval tooling. `--dry-run` reports planned files without writing them.

## Maintenance

`llm-wiki maintenance` reports queue state and review health. It does not merge pages automatically. The active agent should batch-review candidates, merge only explicit, repeated, or clearly reusable facts into existing durable pages, and mark queue items through `pending`, `approved`, `done`, or `skipped`.

```bash
llm-wiki maintenance --workspace <project> --normalize-frontmatter --dry-run
llm-wiki maintenance --workspace <project> --normalize-filenames --apply
llm-wiki maintenance --workspace <project> --apply-lifecycle --dry-run
llm-wiki maintenance --workspace <project> --approve <id> --target wiki/concepts/topic.md
llm-wiki maintenance --workspace <project> --done <id> --target wiki/concepts/topic.md
llm-wiki maintenance --workspace <project> --skip <id> --note "duplicate"
```

`--normalize-frontmatter` merges legacy `source_id` into `source_ids`, fills inferable required core fields, removes redundant defaults, and moves unknown top-level fields under `extensions`. It never applies automatically; run it explicitly, and preview with `--dry-run` first.

`--normalize-filenames` renames curated pages to the naming policy (lowercase ASCII kebab-case, length and shape rules, title↔filename alignment) and appends the prior stem as an alias so existing wikilinks keep resolving. Without `--apply` it only previews the rename plan and any target conflicts; `--apply` performs the rename, backs up the source, appends the alias, and rewrites internal wikilinks. Conflicting target names are skipped for review. It never applies automatically.

`approved` means durable promotion is accepted but not yet merged. `done` means the durable page has been updated. `skipped` means the item was duplicate or not reusable enough. Approved reminders are shown before pending reminders.

Lifecycle hygiene applies only when `llm-wiki maintenance --apply-lifecycle` is run explicitly: candidates remain pending for batch review, old low-signal candidates may move to `skipped`, explicit requests and recovered `result_missing` items are not auto-skipped, old reviewed items beyond the latest 10 move to `outputs/maintenance/archive/YYYY-MM.md`, and known deprecated layout content is moved into the current taxonomy. `raw/inbox/` moves to `raw/sources/`, `raw/assets/` moves to `raw/sources/assets/`, top-level `sources/` moves to `wiki/sources/`, top-level `templates/` moves to `wiki/context/`, and `wiki/entities/` moves to `wiki/concepts` with entity page frontmatter rewritten to `type: "concept"`. Legacy daily live Q&A files are preserved under `outputs/questions/archive/originals/` and converted to chunked `outputs/questions/YYYY-MM-DD/live-qa-001.md` files. The lifecycle does not delete user content to force conformity: duplicate files are deduplicated only when bytes match, conflicts get `*-migrated-<timestamp>` names, and unknown directories are left for lint/agent review. Routine hooks only remind.

Hook reminders are soft:

- session start and instructions loaded may show a one-item summary;
- prompt submit shows one compact reminder for wiki/maintenance prompts, approved items, explicit durable requests, recovered items, or the batch review threshold.

## Fork

`llm-wiki fork --from <source-workspace> --to <target-workspace>` copies durable wiki pages from one workspace wiki tree into another. Each copied page gets a `forked_from` block recording the source workspace, source path, a content hash, and a copy timestamp.

The drift hash intentionally excludes the `forked_from` stamp itself and is computed over NFC-normalized content, so a freshly forked page with no edits reports zero drift. Editing the page body or its non-`forked_from` frontmatter surfaces a `forked-page-drifted` lint warning so sibling workspaces can detect translation edits, status changes, or evidence refresh without manual comparison. Touching only the `forked_from` stamp (for example the copy timestamp) is not treated as drift.

CRLF and BOM source frontmatter is parsed with the same canonical parser used elsewhere, so cross-platform sources fork without structural corruption.

## PreCompact

Pre-compact preservation never blocks compaction. Defaults:

```bash
LLM_WIKI_KIT_PRECOMPACT_ENFORCEMENT=limited
```

`limited` and `soft` emit non-blocking warnings on checkpoint failure. `off` suppresses warnings. `PreCompact` never reads `transcript_path`; checkpoints use bounded, redacted hook-captured turn state only.

## Security

- Full raw transcript capture is disabled by default. An opt-in redacted full Q&A audit log (`LLM_WIKI_KIT_FULL_QA=1`) records every turn's redacted prompt/assistant/tool bodies under `raw/qa/` (local-only, gitignored); see `docs/integrations/opencode.md`.
- Hook payloads are stored as small redacted event envelopes.
- Tool calls are not blocked only because input looks sensitive.
- Tokens, passwords, bearer credentials, private keys, and raw `.env` contents are redacted before durable storage.
- Generated exports are redacted and must not store npm tokens, WinRM credentials, private keys, raw `.env`, or full raw transcripts.
- Phone numbers, emails, dates, and business identifiers are preserved by default because they can be useful local work context.
- `llm-wiki lint` reports secret-like wiki content as an error.

## Release Verification

For `llm-wiki-kit` releases, source tests are not enough. Build one candidate tarball, record its digest, and test that exact file in isolated Linux and native Windows environments before commit or publish:

```bash
npm ci --ignore-scripts
npm test
npm audit --omit=dev --audit-level=high
npm pack --dry-run
git diff --check
npm pack --json --pack-destination /path/to/isolated/candidate
sha256sum /path/to/isolated/candidate/llm-wiki-kit-<version>.tgz
```

Install the candidate tarball into an isolated Linux home and npm prefix, then run `install`, `status`, `doctor`, lint, eval, and memory health through the installed CLI. Do not let this smoke modify the real user's hooks or skill roots. On native Windows, transfer the same tarball and run:

```powershell
pwsh -NoProfile -File .\scripts\windows-runner\verify-release.ps1 `
  -Mode Tarball `
  -PackageSpec C:\path\to\llm-wiki-kit-<version>.tgz `
  -ExpectedVersion <version>
```

The Windows runner performs an isolated tarball install, hook/skill/template status checks, lint/eval/memory/doctor checks, and native NTFS concurrency and atomic-replace tests. Simulated Windows tests do not replace this gate.

After candidate preflight, commit and push only the reviewed release scope. Rebuild from that exact clean pushed SHA, compare the package manifest and digest as appropriate, and repeat Linux/native Windows gates. Publishing requires explicit authority:

```bash
npm publish /path/to/verified/llm-wiki-kit-<version>.tgz
npm view llm-wiki-kit version dist-tags --json
```

Only after publication, install from the registry on Linux and Windows and repeat the minimal `version`, `install`, `status`, `doctor`, `update --check`, and health checks. A registry smoke validates delivery; it must not be the first time the artifact is tested.

Use `NPM_TOKEN` only as an environment variable for authentication. Do not write npm tokens to `.npmrc`, shell history snippets, wiki files, logs, generated exports, or commits.

On root-owned Linux npm prefixes, use sudo only for `npm install -g llm-wiki-kit@<version>`. Run `llm-wiki install`, `post-update`, `status`, and `doctor` as the normal user who owns the Codex/Claude settings.

Native Windows support claims require both a prepublish smoke of the exact candidate tarball and a post-publish registry-install smoke over SSH or the packaged Windows runner. Inspect isolated hook/skill/template state during preflight and the normal user's provider state after authorized publication. The release is not complete until the exact candidate has passed Linux and Windows preflight and the published package has passed both installed-package checks.

## Troubleshooting

If hooks do not run:

```bash
llm-wiki doctor --workspace /path/to/project
llm-wiki status --workspace /path/to/project
llm-wiki install --workspace /path/to/project --profile standard
```

If npm install succeeds but `llm-wiki` is old:

```bash
which -a llm-wiki
readlink -f "$(command -v llm-wiki)"
npm ls -g llm-wiki-kit --depth=0
npm root -g
node "$(npm root -g)/llm-wiki-kit/bin/llm-wiki.js" version
llm-wiki install --workspace /path/to/project --profile standard
hash -r
```

On Windows:

```powershell
where llm-wiki
npm ls -g llm-wiki-kit --depth=0
npm root -g
llm-wiki install --workspace C:\path\to\project --profile standard
llm-wiki doctor --workspace C:\path\to\project
```

If `update` appears slow, use bounded dry runs:

```bash
llm-wiki update --dry-run --workspace /path/to/project --current-only --timeout-ms 30000
llm-wiki update --dry-run --workspace /path/to/search-root --max-dirs 1000 --timeout-ms 30000
```

This file is the source for `llm-wiki manual`. Update it in the same change set as public command, option, hook behavior, directory convention, security policy, language behavior, or update-flow changes.
