# dsh-character-profiler [中文说明](./README.md) DSH writing plugin: **character personality profiling + appearance-weight statistics + behavioral-drift detection**. Quantified consistency monitoring for long-form fiction — every character's personality stays grounded, verifiable, and drift-free. ## Features | Tool | What it does | Cost | | --- | --- | --- | | `novel_profile` | Generate/refresh a **personality profile card** per character: five-dimension personality, motivations, fears, values, speech style (catchphrases/forms of address), behavioral habits, emotional triggers, weaknesses, current growth arc, and consistency red lines; also collects full names/aliases (including third-party forms of address like "old man") | LLM (deep model optional) | | `novel_appearance` | **Appearance weight and share** per character: mention count, paragraph count, dialogue count, per-chapter distribution, weight score (mentions×1 + paragraphs×2 + dialogue×3), share ranking, and protagonist/supporting tier; also flags unregistered suspected characters found in the text | Local only, 0 API | | `novel_deviation` | Detect how much in-text behavior **deviates from the profile**: deviation index 0–100, a list of deviation points (type/severity/quote/suggestion); distinguishes "unforeshadowed OOC flip" from "justified character growth with causal setup" (compared against evolution.json) | LLM | | `novel_profiler_status` | Character consistency overview: character card ↔ profile card comparison, appearance weights, unregistered characters, suggested actions | Local only | ## How it works - Profile cards are written to **`lore/profiles/.md`** under the project. That directory lives under `lore/`, which the writing engine auto-injects into later drafting context — **while drafting, the model keeps seeing each character's consistency red lines**, reducing drift at the source. - Appearance stats auto-derive short names from character card titles ("玛丽安娜·霍斯顿" → 玛丽安娜 / 玛丽 / 霍斯顿); after a profile is generated, LLM-extracted aliases are merged in, getting more accurate with use. - Drift detection compares against the profile card by default; it falls back to the character card when no profile exists and suggests running `novel_profile` first. ## Installation > **Recommended: one-line install via the DSH plugin command** `dsh plugin --profile web add github:MlittleFriend/dsh-character-profiler`, then restart `dsh web` (equivalent to the local script below, without manually copying the directory). 1. Put this directory (`dsh-character-profiler/`) somewhere convenient (e.g. next to your project). 2. Run `install.ps1` (right-click → Run with PowerShell; or `powershell -ExecutionPolicy Bypass -File install.ps1`). 3. **Restart dsh web** (close the current window and re-run your launch command). After restart, a `tool:character-profiler` prompt section should appear in the console. 4. In a new session you can call `novel_profile` / `novel_appearance` / `novel_deviation` / `novel_profiler_status`. > The install script automatically: installs the package into `~/.dsh/profiles/web`, adds the plugin to bundles, and registers the plugin row in the profile's `cordis.patch.yml`. **API config (apiKey/baseURL/model) is inherited at runtime from the `dsh-tool-writing` row** — the key lives in one place only (the tool-writing patch config or an environment variable), no duplication. ## Suggested workflow ``` Start of each volume: novel_profiler_status → see who lacks a profile, whose share looks off New character: novel_profile → create a profile card Routine check: novel_appearance → is any character's weight/share imbalanced? After a few chapters: novel_deviation → check for behavioral drift Arc shift: novel_profile → update the profile (old card is overwritten) ``` ## FAQ - **Character names not matching?** Add a line like `- 别称:玛丽 / 老头子` to the character card, or run `novel_profile` once to have the LLM extract aliases. - **Drift detection always says "consistent"?** Profiles are distilled from the text, so self-consistency is expected; detection is meaningful after new chapters change behavior. Use `perChapter`/`maxParagraphs` to tune granularity. - **Characters without a card** (like "卡尔" in the text) are not counted or checked; `novel_appearance` will prompt you to add a card. ## Development & verification `test-local.mjs` drives the engine directly without restarting the GUI (needs `DSH_WRITING_API_KEY` or reads the key from the profile patch): ```bash node test-local.mjs --stats --root "project-directory" node test-local.mjs --profile --root "project-directory" node test-local.mjs --deviation --root "project-directory" ``` ## License MIT