# Plugin Runtime Hardening Spec > 日期:2026-06-04 > 状态:草案 v1 > 范围:基于优秀 Claude Code 插件调研,对 `webnovel-writer` 的插件形态、运行时可靠性、workflow 编排、doctor 自检、hook 状态感知、eval 与发布治理做系统收束 > 调研样本:`anthropics/claude-plugins-official`、`anthropics/skills`、`obra/superpowers`、`SonarSource/sonarqube-agent-plugins`、`appwrite/claude-plugin`、`aws-samples/sample-claude-code-plugins-for-startups`、社区多插件 marketplace --- ## 1. 背景 `webnovel-writer` 当前已经不是普通单一 Skill,而是一个完整的长篇写作运行时插件: - 7 个 Skill 命令负责 init / plan / write / review / query / learn / dashboard。 - 4 个 Agent 负责写前上下文、审查、事实提取、参考拆解。 - Python CLI 与 `data_modules` 承担 Story System、commit、projection、RAG、memory、Dashboard 数据层。 - `.story-system/` 是合同与提交主链,`.webnovel/*` 是 projection / read-model。 优秀 Claude Code 插件的共同经验是: 1. `SKILL.md` 做路由和流程,不承载全部知识。 2. 确定性动作下沉到脚本 / runtime / MCP,而不是靠 prompt 约束。 3. `commands / skills / agents / hooks / MCP` 边界清楚。 4. hooks 只做轻量状态提示、自检或接线,不做重业务。 5. 复杂 workflow 有可验证的输入、输出、停止条件和验收标准。 6. 有 `doctor / integrate / setup` 类环境自检入口。 7. 有真实行为 eval,证明 agent 会按协议执行。 8. manifest、marketplace、README、版本、LICENSE 有校验,避免漂移。 本 spec 的目标是把这些经验转化为 `webnovel-writer` 的下一阶段架构改造路线。 --- ## 2. 一句话目标 把 `webnovel-writer` 从“强 Skill 包 + Python 工具链”升级为: > 可自检、可验证、可恢复、可重放、可发版治理的长篇写作运行时插件。 --- ## 3. 设计原则 ### 3.1 Runtime First 写章、提交、投影、校验等关键链路必须由 runtime 保证,不再主要依赖 Skill 文档中的自然语言步骤。 ### 3.2 Skill as Router `SKILL.md` 保留: - 何时触发 - 决策树 - 高层流程 - 必读/按需引用路由 - 失败处理边界 `SKILL.md` 不应承担: - 长命令拼接细节 - schema 校验逻辑 - projection 修复逻辑 - 大段题材知识 - 可程序化验证规则 ### 3.3 Commit Is Fact `CHAPTER_COMMIT` 是写后事实,不应和 projection 执行日志混在一起。事实记录与投影执行状态要逐步解耦。 ### 3.4 Hooks Are Advisory Guards hooks 可以承担“自动触发的轻量守卫”,但不能成为隐藏业务流程。 允许: - SessionStart 项目状态摘要 - 依赖 / 配置提醒 - doctor 入口提示 - dashboard / RAG / Story System 健康提示 - skill-scoped 固定预检,且通过时静默 - PreToolUse 对危险写入 / commit 命令做硬阻断 禁止: - 自动写 state / commit / memory - 自动安装外部依赖 - 自动修改正文或设定 - 注入大段创作方法论 - 作为章节主状态机写入 step state - 每个步骤都用 hook 自动打点 - 在用户不可见的情况下推进写作流程 ### 3.5 Behavior Must Be Tested 现有 Python 单元测试继续保留,但不足以证明插件行为。必须增加 skill / agent 工作流级 eval。 ### 3.6 UTF-8 First 本项目大量读取中文路径和中文文件名,新入口必须显式 UTF-8: - Python CLI 入口调用 `enable_windows_utf8_stdio()` 或等价逻辑。 - 所有文本读取 / 写入显式 `encoding="utf-8"`。 - hook / 子进程命令优先使用 `python -X utf8`,或显式设置 `PYTHONUTF8=1`。 - doctor / project-status / write-gate / hook 脚本不得依赖系统默认编码。 ### 3.7 Follow Official `plugin-dev` 后续对本插件的任何新增或修改,必须先遵循官方 `plugin-dev` 插件的指导: ```text C:\Users\lcy\.claude\plugins\marketplaces\claude-plugins-official\plugins\plugin-dev ``` 落地约束: - 插件结构遵循 `plugin-structure`:`.claude-plugin/plugin.json` 必须在插件根的 `.claude-plugin/` 下;`commands/`、`agents/`、`skills/`、`hooks/` 位于插件根层级。 - 所有插件内路径使用 `${CLAUDE_PLUGIN_ROOT}`,不在 manifest / hook / command 中写死本机绝对路径。 - 新增 Skill 遵循 `skill-development`:`SKILL.md` 必须有 `name`、具体触发型 `description`、可选 `version`;正文保持精简,详细规则放入 `references/`,确定性脚本放入 `scripts/`。 - 新增 Command 遵循 `command-development`:使用 markdown + YAML frontmatter,包含清晰 `description`、必要时声明 `argument-hint` 与 `allowed-tools`。 - 新增 Agent 遵循 `agent-development`:frontmatter 补齐 `name`、`description`、`model` / `tools` 等字段;复杂触发场景用示例描述;修改后用 validate-agent 规则检查。 - 新增 Hook 遵循 `hook-development`:插件级 `hooks/hooks.json` 使用 wrapper 格式,即外层包含 `description` 与 `hooks`;命令 hook 使用 `${CLAUDE_PLUGIN_ROOT}`;轻量确定性检查用 command hook,上下文判断才用 prompt hook。 - 修改插件组件后,必须按 `plugin-validator` 思路做结构校验:manifest、commands、agents、skills、hooks、MCP、README、LICENSE、敏感信息与路径可移植性。 这条优先级高于本 spec 中任何自定义落点建议;如果冲突,以官方 `plugin-dev` 约束为准。 --- ## 4. 非目标 本轮不做: - 不重写 Story System 主链语义。 - 不引入大规模新 MCP 服务。 - 不把 37 个题材模板拆成 37 个独立 Skill。 - 不照搬 Superpowers 的高频 git commit 机制。 - 不让 hook 承担写作业务。 - 不在本轮重构 Dashboard 前端信息架构。 - 不改变已有用户项目的数据格式,除非提供兼容读取。 --- ## 5. 目标架构 ### 5.1 组件边界 ```text commands/ 或 Slash Skill 入口 ↓ Skill router(流程、引用路由、失败边界) ↓ Claude Code Todo(过程约束,由宿主管理) ↓ Runtime Gates(写前 / 提交前 / 提交后批量校验) ↓ Agents(context / draft / review / data extract) ↓ Artifact Validator ↓ CHAPTER_COMMIT(事实主链) ↓ Projection Engine(state/index/summary/memory/vector) ↓ Dashboard / Query / Doctor(只读消费) ``` ### 5.2 写章过程管理 不新增独立 resume / step mark / workflow state。Claude Code 本身已经有 Todo 和会话恢复能力,写章过程的步骤约束交给宿主 Todo 管理。 推荐 Todo 形态: ```text [ ] 写前预检与合同刷新 [ ] context-agent 生成写作任务书 [ ] 起草正文 [ ] reviewer 审查 [ ] blocking issue 裁决 / 定点修复 [ ] 润色与排版 [ ] data-agent 提取事实 artifacts [ ] chapter-commit 提交事实 [ ] 验证 projection 与备份 ``` runtime 不维护每一步状态,只提供三个自然边界的批量 gate: - `prewrite`:写前检查项目根、占位符、Story Runtime、章节合同。 - `precommit`:提交前检查正文、review、fulfillment、disambiguation、extraction artifacts。 - `postcommit`:提交后检查 commit、projection、summary、memory、backup。 这样一章最多增加 2-3 次确定性脚本调用,不做每一步打点。 ### 5.3 状态感知模型 项目状态分两层: | 层级 | 负责者 | 持久性 | 用途 | |---|---|---|---| | 会话内进度 | Claude Code Task / Todo | 会话级 | 约束本轮写作步骤、显示当前正在做什么 | | 项目真实状态 | Story System / commit / projection / artifacts | 项目级 | 新对话、resume、doctor 判断下一步 | 不新增独立 workflow state。项目真实状态由 runtime 现场推导: - `.story-system/commits/*.commit.json` 判断最新 accepted/rejected 章节。 - `.story-system/MASTER_SETTING.json` 和章节合同判断下一章目标。 - `.webnovel/tmp/*` artifacts 判断是否已经 review / fulfillment / extraction。 - `.webnovel/projection_log.jsonl` 或兼容字段判断 projection 是否失败。 - draft 文件和 chapter artifact 判断是否存在未提交正文。 新增机器可读的项目状态入口,避免占用现有 `webnovel.py status`。当前 `status` 已转发到 `status_reporter.py`,语义是宏观创作健康报告;本 spec 需要的是短状态摘要,因此使用新命令: ```bash webnovel.py project-status --format json webnovel.py project-status --format summary ``` 示例状态: ```json { "schema_version": "webnovel-project-status/v1", "project": "灵石庄", "latest_accepted_chapter": 12, "target_chapter": 13, "phase": "chapter_contract_ready", "blocking": [], "warnings": ["rag_vector_missing"], "next_action": "run /webnovel-write chapter 13" } ``` `phase` 是一个可推导状态,不是 hook 写入的状态机。phase 词表必须只有一个权威来源,建议新增 `project_phase.py`,由 doctor、project-status、write-gate 共同消费。推荐最小集合: - `no_project` - `unknown` - `init_scaffolded` - `init_ready` - `plan_in_progress` - `chapter_contract_ready` - `draft_in_progress` - `ready_to_commit` - `chapter_committed` - `projection_failed` ### 5.4 Hook 与状态的边界 hook 只读状态、注入短上下文或阻断危险动作: - `SessionStart`:调用 `project-status --format summary`,在新对话、resume、clear、compact 后告诉 Claude 当前项目写到哪里。 - `PreToolUse`:在 `webnovel-write` skill 激活期间,阻断绕过 gate 的 commit / projection 写入。 - `PostToolUse`:可用于把 gate 失败原因补充给 Claude,但不能防止已经发生的副作用。 状态转换只能来自显式 runtime 命令: - `write-gate --stage prewrite/precommit/postcommit` - `chapter-commit` - `projections retry/replay` - 用户显式裁决 blocking issue 这保证流程推进发生在显式 skill / runtime 命令中,而不是 hook 暗中推进。 --- ## 6. Phase 1:`webnovel-doctor` 项目体检入口 ### 6.1 目标 新增只读体检命令,作为现有 `preflight` 的上位诊断入口。`preflight` 已经负责 CLI 环境、project_root 与 `story_runtime` 摘要;`doctor` 必须复用或吸收这些检查,不另造一套并行环境检查。 重点解决三类问题: 1. **文件层面**:目录是否规范、关键文件是否缺失、JSON / SQLite / Markdown 等内容是否符合预期。 2. **系统配置层面**:RAG API / key、Python 依赖、Dashboard 构建产物等运行条件是否完整。 3. **错误解释与修复建议**:缺失或异常时说明影响范围,并给出可执行修复命令或人工处理建议。 `doctor` 不负责判断一章具体该怎么写,也不替代 `write-gate`。它回答的是: > 这个书项目和当前插件运行环境是否完整、可读、可运行;如果不完整,哪里坏了,怎么修。 ### 6.2 入口 CLI: ```bash python -X utf8 webnovel-writer/scripts/webnovel.py --project-root "" doctor --format json ``` Skill: ```text /webnovel-doctor ``` 与现有入口关系: - `preflight`:保留为快速环境检查和兼容入口。 - `doctor`:覆盖 `preflight` 的快检能力,并追加阶段感知文件清单、SQLite、RAG、Python 依赖、Dashboard、修复建议。 - `project-status`:只输出短状态和下一步,不做深度体检。 - `status`:保留现有 `status_reporter.py` 的宏观创作健康报告语义。 可选后续 hook: ```text SessionStart -> 打印 project-status 摘要;异常时提示运行 /webnovel-doctor ``` ### 6.3 模式 默认模式必须只做本地只读检查: ```bash webnovel.py doctor --format json webnovel.py doctor --format text ``` 可选深度模式才允许做慢检查或外部连通性检查: ```bash webnovel.py doctor --deep --format json ``` 可选章节模式用于检查指定章节相关 artifacts: ```bash webnovel.py doctor --chapter 13 --format json ``` 默认 `doctor` 禁止: - 写任何文件。 - 自动修复。 - 自动安装 Python / Node 依赖。 - 自动启动 Dashboard。 - 默认联网测试 RAG API。 ### 6.4 阶段感知的期望文件清单 `doctor` 必须先判断项目当前阶段,再决定“这个阶段应该有哪些文件”。不能用最终态清单检查所有项目。 #### 6.4.1 阶段推导 阶段由共享 `project_phase.py` 现场推导,不写任何状态文件。doctor、project-status、write-gate 必须消费同一个 resolver,避免出现多套 phase 词表: | phase | 判定依据 | 含义 | |---|---|---| | `no_project` | project root 无效,或没有 `.webnovel/state.json` | 尚未初始化或未绑定书项目 | | `unknown` | 文件状态不足以稳定判断 | 只做低风险检查 | | `init_scaffolded` | 有 `.webnovel/state.json`、基础目录、设定集/总纲,但没有 `.story-system/MASTER_SETTING.json` | `webnovel.py init` 刚结束,Story System 尚未生成 | | `init_ready` | 有 `.webnovel/state.json`、基础设定集、`大纲/总纲.md`、`.story-system/MASTER_SETTING.json` | init 完成,可进入 plan | | `plan_in_progress` | 有 MASTER_SETTING,但卷/章合同不完整 | 正在规划,尚不能直接写章 | | `chapter_contract_ready` | 指定章节有 volume / chapter / review 合同 | 可进入写前上下文和起草 | | `draft_in_progress` | 指定章节有正文草稿或 `.webnovel/tmp` artifacts | 写章中或审查中 | | `ready_to_commit` | review / fulfillment / disambiguation / extraction artifacts 都存在 | 可进入 precommit gate | | `chapter_committed` | 指定章节有 commit | 章节已提交,检查 projection | | `projection_failed` | latest commit 有 `projection_status.failed:*` | read-model 不可信,需要修复 | 如果无法确定阶段,返回 `phase=unknown`,并只做低风险文件可读性检查。 #### 6.4.2 阶段期望清单 `doctor` 输出必须包含当前阶段的期望清单: ```json { "phase": "init_ready", "expected_profile": "after_init", "expected_files": { "required": [ ".webnovel/state.json", ".webnovel/summaries/", "设定集/世界观.md", "设定集/力量体系.md", "设定集/主角卡.md", "设定集/反派设计.md", "大纲/总纲.md", ".env.example", ".story-system/MASTER_SETTING.json" ], "conditional": [ "设定集/主角组.md", "设定集/女主卡.md" ], "not_expected_yet": [ ".story-system/volumes/volume_001.json", ".story-system/chapters/chapter_001.json", ".story-system/reviews/chapter_001.review.json", ".story-system/commits/chapter_001.commit.json", ".webnovel/summaries/chapter_001.md", ".webnovel/memory_scratchpad.json" ] } } ``` `conditional` 文件必须根据 `state.json` 判断。例如: - `protagonist_structure` 是多主角 / 主角组时,才要求 `设定集/主角组.md`。 - `heroine_config` 不是无女主时,才要求 `设定集/女主卡.md`。 - 无金手指项目不要求单独 `金手指设计.md`。 #### 6.4.3 init 刚结束的判定 `webnovel.py init` 刚结束时,合理期望是项目骨架完整,但不要求写作后产物。 必须存在: ```text .webnovel/ .webnovel/backups/ .webnovel/archive/ .webnovel/summaries/ .webnovel/state.json 设定集/ 设定集/世界观.md 设定集/力量体系.md 设定集/主角卡.md 设定集/反派设计.md 大纲/ 大纲/总纲.md 正文/ 审查报告/ .env.example ``` 如果 `/webnovel-init` 已完成 Story System 初始化,还必须存在: ```text .story-system/ .story-system/MASTER_SETTING.json .story-system/anti_patterns.json ``` init 阶段不应该要求: ```text .story-system/volumes/volume_001.json .story-system/chapters/chapter_001.json .story-system/reviews/chapter_001.review.json .story-system/commits/chapter_001.commit.json .webnovel/summaries/chapter_001.md .webnovel/memory_scratchpad.json .webnovel/vectors.db ``` 缺这些只能返回 `skip` 或 `info`,不能作为 warning / blocker。 #### 6.4.4 plan / write / commit 阶段清单 规划完成后,才开始要求: ```text .story-system/volumes/volume_001.json .story-system/chapters/chapter_001.json .story-system/reviews/chapter_001.review.json ``` 写章中,才开始检查: ```text .webnovel/tmp/review_results.json .webnovel/tmp/fulfillment_result.json .webnovel/tmp/disambiguation_result.json .webnovel/tmp/extraction_result.json ``` commit 后,才开始要求: ```text .story-system/commits/chapter_001.commit.json .webnovel/summaries/chapter_001.md .webnovel/index.db ``` RAG 向量库永远是增强项: ```text .webnovel/vectors.db ``` 缺失或为空默认只返回 warning,并说明会降级 BM25;在用户显式要求语义检索或 `--deep --require-rag` 时才可升级为 blocker。 #### 6.4.5 误报控制 `doctor` 的严重级别必须基于“当前阶段 + 用户目标”判断: | 情况 | 阶段 | 结果 | |---|---|---| | 缺 commit | `init_ready` | `skip` / `info` | | 缺 commit | `ready_to_commit` | `blocker` | | 缺 summary | `init_ready` | `skip` / `info` | | 缺 summary | `chapter_committed` 且 projection summary=done | `blocker` | | 缺 vectors.db | 任意默认模式 | `warning` | | 缺 MASTER_SETTING | `init_scaffolded` | `warning`,提示运行 story-system persist | | 缺 MASTER_SETTING | `plan_in_progress` 或之后 | `blocker` | ### 6.5 文件 / 数据结构检查 `doctor` 必须把“肉眼难看见”的项目文件和数据库结构变成可读报告。 #### 6.5.1 目录结构 检查: - project root 是否有效,且不是插件目录本身。 - `.webnovel/` 是否存在。 - `.story-system/` 是否存在。 - `正文/`、`大纲/`、`设定集/` 等书项目目录是否存在。 - 用户项目文件是否误写入插件目录。 判定: - project root 无效:`blocker`。 - 缺 `.webnovel/` 或 `.story-system/`:`blocker` 或 `warning`,取决于是否是刚 init 的项目。 - 缺正文/大纲/设定集目录:`warning`,并提示初始化或补建。 #### 6.5.2 Story System 主链文件 检查: - `.story-system/MASTER_SETTING.json` 是否存在、JSON 可读、`meta.contract_type` 是否正确。 - `volumes/volume_*.json` 是否存在、JSON 可读。 - `chapters/chapter_*.json` 是否存在、JSON 可读。 - `reviews/chapter_*.review.json` 是否存在、JSON 可读。 - `commits/chapter_*.commit.json` 是否存在、JSON 可读。 - latest commit 的 `meta.status` 是否是 `accepted` / `rejected`。 - latest commit 的 `provenance.write_fact_role` 是否为 `chapter_commit`。 判定: - 主链 JSON 读不出来:`blocker`。 - 已进入写作流程但缺 MASTER_SETTING:`blocker`。 - latest commit schema 明显不合法:`blocker`。 - 新项目尚无 commit:`info` 或 `warning`,不能误报为错误。 #### 6.5.3 Projection / Read-model 文件 检查: - `.webnovel/state.json` 是否存在、JSON 可读、基础字段可解析。 - `.webnovel/summaries/` 是否存在,最新 accepted 章节是否有 summary。 - `.webnovel/memory_scratchpad.json` 是否存在、JSON 可读、基础结构可解析。 - latest commit 的 `projection_status` 是否有 `pending` / `failed:*`。 判定: - `state.json` 不可读:`blocker`。 - projection writer failed:`blocker`,因为后续查询和 dashboard 可能不可信。 - summary / memory 缺失:通常 `warning`,除非对应 projection 标记为 done 但实物不存在。 #### 6.5.4 SQLite 数据库 检查 `.webnovel/index.db`: - 文件是否存在。 - SQLite 是否可打开。 - 关键表是否存在。 - 关键表行数是否异常。 - 基础查询是否能执行。 建议首批关键表: ```text entities relationships story_events review_metrics writing_checklist_scores override_ledger ``` 检查 `.webnovel/vectors.db`: - 文件是否存在。 - SQLite 是否可打开。 - `vectors` 表是否存在。 - vector 行数。 - `bm25_index` / `doc_stats` 是否存在。 数据库报告必须显式展示表和行数,例如: ```json { "id": "db.index.tables", "status": "ok", "severity": "info", "path": ".webnovel/index.db", "tables": { "entities": 128, "relationships": 42, "story_events": 36, "review_metrics": 12 } } ``` 判定: - `index.db` 不存在或打不开:`blocker`。 - `story_events` 缺失:`warning` 或 `blocker`,取决于当前是否已经有 accepted commit。 - `vectors.db` 缺失:`warning`,RAG 可降级 BM25。 - `vectors` 行数为 0:`warning`。 #### 6.5.5 Reference / CSV 文件 检查: - `references/csv/*.csv` 是否存在。 - 必要 CSV 表头是否符合预期。 - 题材别名、题材与调性推理、反模式等核心表是否可读。 - 明显占位符是否残留。 判定: - 核心 CSV 不可读或表头缺失:`warning`。 - 会导致 story-system 无法生成 MASTER_SETTING 的缺失:`blocker`。 ### 6.6 系统 / 配置检查 #### 6.6.1 Python 依赖 检查: - 当前 Python 版本。 - `scripts/requirements.txt` 是否存在。 - 核心包是否可 import。 首批核心包: ```text pydantic numpy requests fastapi uvicorn watchdog ``` 判定: - 运行 CLI 必需包缺失:`blocker`。 - Dashboard 专用包缺失:`warning`,除非用户正在运行 dashboard skill。 #### 6.6.2 RAG 配置 默认模式检查: - `.env` / 环境变量是否能读到 embedding 配置。 - embed base_url / model 是否配置。 - embed api_key 是否存在。 - rerank base_url / model / api_key 是否存在。 - `vectors.db` 是否存在且有数据。 - 当前推断 RAG 模式:`full` / `embed_only` / `bm25_only`。 `--deep` 模式才检查: - embed API 是否真实可调用。 - rerank API 是否真实可调用。 - API 返回维度是否与已有 vectors 兼容。 判定: - 缺 RAG key:`warning`,必须明确说明会降级到 BM25。 - API 连通失败:`warning` 或 `blocker`,取决于用户是否要求必须语义检索。 - base_url / model 明显空缺:`warning`。 #### 6.6.3 Dashboard / Node 检查: - `dashboard/frontend/dist/index.html` 是否存在。 - dashboard 后端模块是否能 import。 - `dashboard/requirements.txt` 是否存在。 - `dashboard/frontend/package.json` 是否存在。 默认不检查: - 不自动 `npm install`。 - 不自动启动服务。 - 不默认检查 localhost 端口。 判定: - dist 缺失:`warning`,提示重新 build。 - FastAPI 依赖缺失:`warning`。 ### 6.7 输出格式 每条检查必须包含: - `id`:稳定错误码,方便测试和 UI 展示。 - `status`:`ok` / `fail` / `warn` / `skip`。 - `severity`:`blocker` / `warning` / `info`。 - `path`:相关文件路径,没有则为空。 - `expected`:预期状态。 - `actual`:实际状态。 - `impact`:对用户有什么影响。 - `repair`:修复命令或人工修复建议。 ```json { "ok": false, "project_root": "...", "mode": "default", "phase": "chapter_committed", "expected_profile": "after_commit", "blocking_count": 1, "warning_count": 2, "expected_files": { "required": [".webnovel/state.json", ".story-system/commits/chapter_001.commit.json"], "not_expected_yet": [] }, "checks": [ { "id": "db.index.missing_table", "status": "fail", "severity": "blocker", "path": ".webnovel/index.db", "expected": "table story_events exists", "actual": "table missing", "impact": "无法确认 accepted commit 的事件链是否完成投影", "repair": { "command": "webnovel.py projections replay --from 1 --to latest --writers index", "manual": "如果 replay 尚未实现,先重新执行最近章节的 chapter-commit 或从备份恢复 index.db" } } ], "recommended_actions": [ { "command": "webnovel.py rag stats", "reason": "vectors.db missing; semantic retrieval will fall back to BM25", "severity": "warning" } ] } ``` ### 6.8 错误码命名 错误码按域划分: ```text project.root.invalid project.phase.unknown project.expected_file.missing project.structure.missing_dir story.master.missing story.commit.invalid_json story.commit.invalid_status projection.status.failed projection.file.missing db.index.unreadable db.index.missing_table db.vector.empty rag.embed.key_missing rag.embed.api_unreachable python.import_missing dashboard.dist_missing reference.csv.invalid_header artifact.schema_error ``` ### 6.9 文件落点 - `webnovel-writer/scripts/data_modules/doctor.py` - `webnovel-writer/scripts/data_modules/project_phase.py` - `webnovel-writer/scripts/data_modules/project_status.py` - `webnovel-writer/scripts/data_modules/webnovel.py` - `webnovel-writer/skills/webnovel-doctor/SKILL.md` - `webnovel-writer/scripts/data_modules/tests/test_doctor.py` - `webnovel-writer/scripts/data_modules/tests/test_project_phase.py` - `webnovel-writer/scripts/data_modules/tests/test_project_status.py` - `docs/guides/commands.md` ### 6.10 验收 - 空项目返回 `ok=false`,但不写任何文件。 - init 刚结束时能识别 `phase=init_scaffolded` 或 `phase=init_ready`,并返回该阶段的 `expected_files`。 - init 刚结束时缺 commit / summary / memory / vectors.db 不得返回 blocker。 - init 刚结束时缺 `state.json`、`设定集/世界观.md`、`大纲/总纲.md` 必须返回 blocker 或 warning,并给出补救命令。 - `MASTER_SETTING.json` 在 `init_scaffolded` 阶段缺失是 warning,在 plan/write 阶段缺失是 blocker。 - 正常项目返回 `ok=true`,并显示 `index.db` / `vectors.db` 的关键表和行数。 - 缺 `state.json` 返回 `project.structure` 或 `projection.file` 类 blocker。 - `index.db` 缺关键表时返回稳定错误码、影响说明和修复建议。 - `vectors.db` 缺失或为空时返回 warning,并明确说明 RAG 会降级到 BM25。 - 缺 RAG key 时返回 warning,不阻断普通写作。 - Python 必需包缺失时返回 blocker,并提示安装 `scripts/requirements.txt`。 - Dashboard dist 缺失时返回 warning,并提示 build 命令。 - latest commit projection failed 时返回 actionable command。 - 默认模式不联网、不安装依赖、不启动服务、不写文件。 - `--deep` 模式可进行 RAG API ping,但必须明确标记为 deep check。 - `preflight` 仍可运行;其结果与 doctor 的快检部分不冲突。 - 所有中文路径和中文文件读取在 Windows 下使用 UTF-8,不因默认 GBK 失败。 --- ## 7. Phase 2:章节 Runtime Gates ### 7.1 目标 不重造一套 workflow/resume 系统。把 `/webnovel-write` 中最容易出错的关键边界下沉为批量校验 gate,过程顺序由 Claude Code Todo 约束。 实施顺序上,Runtime Gates 必须依赖 Artifact Validator 的统一错误语义;本节描述 gate 设计,不代表先于 validator 开工。 ### 7.2 新增模块 建议新增 gate 外壳,但 `prewrite` 必须包装或迁移现有 `PrewriteValidator`,不得重写一套占位符和合同判断逻辑: ```text webnovel-writer/scripts/data_modules/write_gates/ __init__.py prewrite.py precommit.py postcommit.py ``` 已有复用点: - `webnovel-writer/scripts/data_modules/prewrite_validator.py` - `webnovel-writer/scripts/data_modules/tests/test_prewrite_validator.py` ### 7.3 Gate 设计 不写 `.workflow.json`,不维护 step state。每次 gate 根据现有项目文件和 artifacts 现场计算结果。 统一输出: ```json { "schema_version": "write-gate/v1", "chapter": 12, "stage": "precommit", "ok": false, "blocking": [ { "type": "pending_disambiguation", "detail": "disambiguation_result.pending is not empty" } ], "warnings": [], "artifacts": { "review_result": ".webnovel/tmp/review_results.json", "fulfillment_result": ".webnovel/tmp/fulfillment_result.json", "disambiguation_result": ".webnovel/tmp/disambiguation_result.json", "extraction_result": ".webnovel/tmp/extraction_result.json" } } ``` ### 7.4 Gate 职责 runtime gate 负责: - 校验必要文件存在。 - 校验 JSON schema。 - prewrite 阶段复用 `PrewriteValidator`。 - 判定 blocking issue。 - 判定是否允许进入下一自然阶段。 - 输出明确的失败原因和建议命令。 runtime gate 不负责: - 代替 LLM 起草正文。 - 代替 Agent 做审查。 - 自动决定用户裁决。 - 记录每一步进度。 - 替代 Claude Code Todo / 会话恢复能力。 ### 7.5 CLI 子命令 ```bash webnovel.py write-gate --chapter N --stage prewrite --format json webnovel.py write-gate --chapter N --stage precommit --format json webnovel.py write-gate --chapter N --stage postcommit --format json ``` ### 7.6 Skill 改动 `webnovel-write/SKILL.md` 改为: 1. 使用 Claude Code Todo 建立本章流程清单。 2. 调 `write-gate --stage prewrite`,通过后才写。 3. 调 context-agent。 4. 起草正文。 5. 调 reviewer。 6. blocking issue 由 Todo 记录并裁决 / 定点修复。 7. 润色后调 data-agent。 8. 调 `write-gate --stage precommit`,通过后才提交。 9. 调 chapter-commit。 10. 调 `write-gate --stage postcommit`,通过后才宣布完成。 ### 7.7 验收 - 缺 `review_results.json` 时不允许进入 commit。 - reviewer 有 blocking issue 时 `precommit.ok=false`。 - disambiguation pending 非空时 `precommit.ok=false`。 - projection failed 时 `postcommit.ok=false`。 - gate 调用次数控制在每章 2-3 次,不做逐步 mark。 --- ## 8. Phase 3:Artifact Validator ### 8.1 目标 统一校验所有 agent 产物,避免字段名漂移、包错外层、缺 required 字段。 ### 8.2 校验对象 - `review_results.json` - `fulfillment_result.json` - `disambiguation_result.json` - `extraction_result.json` - `chapter_XXX.commit.json` - `projection_status` 权威 schema 来源: - `review_results.json`、`fulfillment_result.json`、`disambiguation_result.json`、`extraction_result.json` 默认以 `chapter_commit_schema.py` 中 commit 所需的 Pydantic model 为准。 - `review_schema.py` 和 `entity_linker.py` 中同名 / 近名模型只作为上游工具局部模型,不作为 commit artifact 的最终权威。 - 如需兼容上游局部模型输出,必须在 `artifact_validator.py` 显式做 normalize,并在输出中标注兼容来源。 ### 8.3 输出错误分类 ```text schema_error missing_artifact blocking_review missed_outline_node pending_disambiguation commit_rejected projection_failure unsafe_project_root placeholder_blocker ``` ### 8.4 文件落点 - `webnovel-writer/scripts/data_modules/artifact_validator.py` - `webnovel-writer/scripts/data_modules/tests/test_artifact_validator.py` - `webnovel-writer/scripts/data_modules/write_gates/precommit.py` ### 8.5 验收 - `extraction_result.json` 外层包成 `{"extraction": ...}` 时返回 schema_error。 - `state_deltas` 使用旧字段名时能兼容或给出明确诊断。 - `disambiguation_result.pending` 非空时阻断 commit。 - `fulfillment_result.missed_nodes` 非空时阻断 accepted commit。 - `ReviewResult` / `DisambiguationResult` 等同名模型不再各自漂移,validator 明确以 commit artifact schema 为准。 --- ## 9. Phase 4:Commit 不可变与 Projection Log 外置 ### 9.1 当前问题 当前 `ChapterCommitService` 会: 1. build commit。 2. persist commit。 3. apply projections。 4. 将 `projection_status` 写回 commit。 这让 commit 同时承担“事实记录”和“投影执行日志”两个职责。 ### 9.2 目标 将事实与投影执行状态拆开: ```text .story-system/commits/chapter_012.commit.json # 不可变事实 .webnovel/projection_log.jsonl # 投影执行日志 index.db.projection_runs # 可查询投影状态 ``` ### 9.3 迁移策略 Phase 4 不强制立刻删除 commit 内 `projection_status`,采用双写过渡: 1. 保留 commit 内 projection_status 兼容 Dashboard。 2. 新增 projection log。 3. Dashboard / doctor 优先读取 projection log。 4. 后续版本再将 commit 内 projection_status 标记 deprecated。 ### 9.4 Projection Run Schema ```json { "run_id": "ch012-20260604T102233", "chapter": 12, "commit_path": ".story-system/commits/chapter_012.commit.json", "commit_hash": "sha256:...", "writer": "memory", "status": "done", "started_at": "...", "finished_at": "...", "error": "", "retry_of": "" } ``` ### 9.5 文件落点 - `webnovel-writer/scripts/data_modules/projection_log.py` - `webnovel-writer/scripts/data_modules/chapter_commit_service.py` - `webnovel-writer/scripts/data_modules/tests/test_projection_log.py` - `webnovel-writer/dashboard/app.py` - `webnovel-writer/scripts/data_modules/story_runtime_health.py` ### 9.6 验收 - 每个 writer 执行后都有 projection log。 - 单 writer failed 不影响其他 writer 记录。 - doctor 能指出 failed writer 和建议重跑命令。 - commit 文件 hash 在 projection log 中可追溯。 --- ## 10. Phase 5:Projection Replay / Retry ### 10.1 目标 投影失败时可以只补跑失败 writer,尤其是 vector / RAG 等外部依赖。 ### 10.2 CLI ```bash webnovel.py projections status --chapter N webnovel.py projections retry --chapter N --writer vector webnovel.py projections retry-failed --chapter N webnovel.py projections replay --from 1 --to 20 --writers state,index,summary ``` ### 10.3 约束 - replay 只能读取 accepted commit。 - rejected commit 只允许 state writer 更新状态。 - writer 必须幂等。 - retry 不得修改 commit 事实内容。 ### 10.4 文件落点 - `webnovel-writer/scripts/data_modules/projection_runner.py` - `webnovel-writer/scripts/data_modules/event_projection_router.py` - projection writer 幂等性测试 ### 10.5 验收 - 删除 `summaries/chapter_012.md` 后 retry summary 可恢复。 - vector API key 缺失时 vector failed,其余 writer done。 - 配置 key 后 retry vector 只补 vector。 - replay 1-5 后 state/index/summary 与 commit 链一致。 --- ## 11. Phase 6:Skill / Agent 契约补强 ### 11.1 Skill Frontmatter 7 个现有 Skill 的 `description` 要从单句说明升级为召回规则: - 何时使用。 - 典型触发词。 - 不适用场景。 - 是否有副作用。 示例: ```yaml description: Use when the user wants to draft, continue, rewrite, or commit a numbered webnovel chapter. Runs the full context -> draft -> review -> polish -> fact extraction -> chapter commit workflow. Do not use for pure status queries, project initialization, or dashboard-only requests. ``` ### 11.2 Agent Frontmatter 所有 agent 补齐: - `name` - `description` - `tools` - `model` 可选 - `output_schema` - `failure_statuses` ### 11.3 Agent 分工调整 现有: - `context-agent` - `reviewer` - `data-agent` - `deconstruction-agent` 建议新增或拆分: - `continuity-reviewer`:设定 / 时间线 / 人物状态 / 伏笔合规。 - `style-reviewer`:文风 / AI 味 / 句式重复 / 排版。 - `reader-pull-reviewer`:爽点 / 钩子 / 微兑现 / 追读力。 短期可以先不新增文件,而是在 `reviewer` 输出 schema 中拆维度;中期再拆 agent。 ### 11.4 验收 - prompt integrity 测试确认所有 Skill 有足够长的 description。 - agent 输出 schema 可被 artifact validator 校验。 - data-agent 文档中仍明确“不直接写 state/index/summaries/memory”。 --- ## 12. Phase 7:Behavior Evals ### 12.1 目标 学习 Superpowers 的 headless 行为测试思路,补上“插件是否按协议执行”的验证层。 ### 12.2 Eval 类型 新增: ```text evals/ skill-triggering/ workflow-behavior/ agent-output-schema/ continuity-conflict/ memory-commit/ ``` ### 12.3 首批用例 | Eval | 目标 | |---|---| | init_project_safety | 不在插件目录生成项目,不污染 canon | | plan_outputs_executable_chapter_tasks | 章纲包含目标情绪、人物变化、伏笔、禁写事项 | | write_blocks_on_review_blocking_issue | blocking issue 不进入 commit | | data_agent_never_writes_projection | data-agent 只产出 artifacts | | commit_drives_projection | accepted commit 后 projection writer 被触发 | | query_falls_back_explicitly | 主链缺失时 query 明确说明 fallback | | dashboard_readonly | Dashboard API 不提供写接口 | ### 12.4 Runner 先做轻量 runner: ```bash python webnovel-writer/scripts/run_behavior_evals.py --case write_blocks_on_review_blocking_issue ``` 如果本地没有 Claude Code CLI,则 eval 可跳过 transcript 测试,只跑 artifact fixture 测试。 ### 12.5 验收 - 每个 Skill 至少有 1 个 eval。 - `webnovel-write` 至少覆盖成功链路和 blocking 链路。 - eval 输出 JSON 报告,包含 pass/fail/reason/artifacts。 --- ## 13. Phase 8:Manifest / Marketplace / 发布治理 ### 13.1 目标 防止插件元数据、README、marketplace、version 之间漂移。 ### 13.2 校验脚本 新增: ```bash python webnovel-writer/scripts/validate_plugin_package.py ``` 检查: - 根 `.claude-plugin/marketplace.json` 存在。 - 插件 `.claude-plugin/plugin.json` 存在。 - marketplace version 与 plugin.json version 一致。 - README / 现有 CI 使用的版本位置与 plugin.json 一致;不得新增一套与既有 Plugin Version Check 冲突的 README 版本规则。 - 每个 `skills/*/SKILL.md` 有 frontmatter。 - 每个 `agents/*.md` 有 frontmatter。 - LICENSE 存在。 - Dashboard dist 存在。 - `scripts/requirements.txt` 与根 `requirements.txt` 可解析。 - docs 命令表与实际 Skill 名称一致。 ### 13.3 可选 manifest 增强 如 Claude Code manifest 支持,可补: - `commands` - `agents` - `hooks` - `mcpServers` - user config schema - screenshots / assets 如果当前宿主不需要显式声明,则保持默认目录发现,避免过度配置。 ### 13.4 验收 - clean clone 后 validate 通过。 - 修改 version 任一处导致 validate 失败。 - 删除一个 Skill frontmatter 导致 validate 失败。 - 版本校验复用或对齐现有 CI 规则,不与 README 版本表 / badge 检查互相打架。 --- ## 14. Phase 9:轻量 SessionStart Hook(可选) ### 14.1 目标 新增可选 hook,在会话启动、resume、clear、compact 时提示项目状态。该 hook 是状态观察器,不是状态机。 ### 14.2 输出 ```text Webnovel Writer initialized. project: 灵石庄 story runtime: mainline ready, latest chapter 12 accepted projections: 4 done, 1 failed(vector) rag: BM25 fallback; EMBED_API_KEY missing next: run /webnovel-doctor for details ``` ### 14.3 约束 - 只读。 - 不安装依赖。 - 不写任何文件。 - 输出不超过 8 行。 - 正常状态下只输出摘要,不输出完整 JSON。 - 失败时给出一个下一步命令,不展开长诊断。 - 可通过环境变量关闭: ```text WEBNOVEL_DISABLE_SESSION_HOOK=1 ``` ### 14.4 文件落点 - `webnovel-writer/hooks/hooks.json` - `webnovel-writer/hooks/session_start.py` - `webnovel-writer/.claude-plugin/plugin.json` 或默认 hook 发现路径 - `docs/operations/operations.md` ### 14.5 验收 - 无项目根时不报错,只提示未绑定项目。 - 有项目根时调用 `project-status --format summary` 或 doctor summary。 - 设置 disable env 后无输出。 - resume 后能刷新 latest chapter / projection 状态。 - 输出不会超过 1000 字符。 ### 14.6 Skill-scoped 预检 Hook(可选) 对 `/webnovel-write` 这类高风险 skill,可以在 skill frontmatter 中挂轻量 hook: - `PreToolUse(Bash)`:对直接运行 `chapter_commit.py`、`webnovel.py chapter-commit` 或 projection 写入命令做 best-effort 提醒 / 兜底阻断。Bash 字符串解析不能作为唯一可靠保证,真正的强保证必须在 runtime gate 和 commit 入口中实现。 - `PreToolUse(Write|Edit)`:如果目标路径是 `.story-system/` commit、`.webnovel/state.json`、`index.db`、`memory_scratchpad.json` 等 projection 产物,则要求走 runtime 命令。 - hook 通过时必须静默;只在阻断时返回简短原因。 不建议把所有固定预检都放进 hook。推荐分层: | 预检类型 | 放在哪里 | |---|---| | 新会话状态摘要 | plugin-level `SessionStart` hook | | 是否能开始写本章 | `write-gate --stage prewrite` | | 是否能提交本章 | `write-gate --stage precommit` | | 是否能宣布完成 | `write-gate --stage postcommit` | | 禁止绕过 runtime 写主链 | skill-scoped `PreToolUse` hook | | 复杂修复建议 | `/webnovel-doctor` skill | ## 15. 推荐实施顺序 1. `project_phase` + `project-status` + `webnovel-doctor`:先建立统一阶段推导、短状态和只读自检基本盘。 2. `Artifact Validator`:统一错误语义。 3. `Runtime Gates`:用写前 / 提交前 / 提交后批量校验约束关键边界,其中 prewrite 复用 `PrewriteValidator`。 4. `Projection Log`:事实与投影日志解耦。 5. `Projection Retry / Replay`:补恢复能力。 6. `Skill / Agent 契约补强`:降低 prompt 漂移。 7. `Behavior Evals`:证明插件协议有效。 8. `Plugin Package Validator`:发布治理。 9. 可选 `SessionStart Hook`:只读状态提示。 10. 可选 `Skill-scoped PreToolUse Hook`:阻断绕过 runtime 的危险写入。 --- ## 16. 验收总表 | 能力 | 验收标准 | |---|---| | Doctor | 能只读报告目录/文件/数据库完整性、RAG/Python/Dashboard 配置,并给出修复建议 | | Project Status | 能从主链和 artifacts 推导当前章节阶段,不占用既有 `status_reporter.py` 语义,不写 workflow state | | Runtime Gates | `/webnovel-write` 在写前、提交前、提交后三个自然边界有批量校验 | | Validator | agent 产物 schema 漂移能被统一诊断 | | Commit | commit 事实与 projection log 可分离追溯 | | Replay | vector/summary 等投影失败后可单独 retry | | Skills | 7 个 Skill description 足够路由,长知识按需加载 | | Agents | agent 有工具范围、输出 schema、失败状态 | | Evals | 每个 Skill 至少 1 个行为 eval | | Package | manifest / marketplace / README / version 可校验 | | Hook | 如果启用,SessionStart 只读短输出,PreToolUse 只做危险动作阻断 | --- ## 17. 风险 ### 17.1 过度工程化 风险:为了学习优秀插件,把当前系统拆得太碎。 控制:先做 doctor / validator / runtime gates 三个高收益模块,不急着拆 37 个题材 Skill。 ### 17.2 Hook 副作用 风险:hook 自动执行导致用户不信任插件。 控制:SessionStart hook 只读,PreToolUse hook 只阻断危险动作;所有修复和推进必须由 skill / runtime 显式触发。 ### 17.3 Hook 状态机漂移 风险:如果 hook 自己写状态,可能与 commit / projection / Todo 产生三套真相。 控制:状态由共享 `project_phase` / `project-status` 现场推导;hook 不写状态;流程推进只由显式 skill / runtime 命令触发。 ### 17.4 Commit 迁移破坏 Dashboard 风险:projection_status 外置后 Dashboard 读不到状态。 控制:先双写,Dashboard 优先读新 projection log,旧字段保留一个版本周期。 ### 17.5 Eval 成本高 风险:headless Claude 行为 eval 慢且贵。 控制:分 fast fixture eval 和 slow transcript eval;CI 默认只跑 fast。 ### 17.6 Skill 触发变化 风险:description 改长后触发行为变化。 控制:增加 skill-triggering eval,先验证再发布。 --- ## 18. 不变量 无论如何重构,必须保持: 1. `.story-system/` 是主链真源。 2. accepted `CHAPTER_COMMIT` 是写后事实入口。 3. `.webnovel/state.json`、`index.db`、`summaries/`、`memory_scratchpad.json` 是 projection / read-model。 4. `data-agent` 不直接写 projection。 5. Dashboard 默认只读。 6. RAG key 缺失必须可降级到 BM25。 7. 用户项目文件不能写到插件目录。 8. hook 不是项目状态真源。 9. `webnovel.py status` 继续保留宏观创作健康报告语义,短状态使用 `project-status`。 --- ## 19. 第一批可开工任务 1. 新增 `project_phase.py`,统一 doctor / project-status / gates 的 phase 推导。 2. 新增 `project_status.py`,注册 `project-status` 子命令,保留现有 `status` 转发到 `status_reporter.py`。 3. 新增 `doctor.py`,复用现有 `preflight` / `build_story_runtime_health()`。 4. 在统一 CLI 注册 `doctor` 子命令。 5. 新增 `/webnovel-doctor` Skill。 6. 新增 `artifact_validator.py`,先包装 `chapter_commit_schema.py` 中的 commit artifact Pydantic schema。 7. 给 `webnovel-write` 的四类 agent artifact 增加 validator 测试 fixture。 8. 新增 `write_gates/prewrite.py`、`write_gates/precommit.py`、`write_gates/postcommit.py`,其中 prewrite 包装 `PrewriteValidator`。 9. 修改 `webnovel-write/SKILL.md`,开始引用 `write-gate --stage prewrite/precommit/postcommit`,过程管理仍使用 Claude Code Todo。 10. 先审计 5 个 projection writer 的幂等性,再新增 `projection_log.py`。 11. 给 7 个 Skill 补 description。 12. 新增 `validate_plugin_package.py`,先对齐现有版本 CI,再校验 frontmatter / LICENSE / dist。 13. 新增可选 SessionStart hook,只注入 project-status summary。 14. 新增可选 skill-scoped PreToolUse hook,作为 best-effort 兜底提醒 / 阻断。 --- ## 20. 最终判断 `webnovel-writer` 当前最大短板不是知识库不足,也不是题材模板不够,而是: > 关键流程仍有一部分靠 Skill 文档和 Agent 遵守协议来保证。 本 spec 的核心就是把这些协议逐步变成 runtime 可验证机制: - doctor 负责知道项目文件、数据库和系统配置是否完整可用; - project-status 负责用统一 phase resolver 知道项目现在写到哪里; - runtime gates 负责知道关键边界是否可继续; - validator 负责知道产物是否可信; - projection log 负责知道 read-model 是否同步; - eval 负责证明 agent 真的按协议执行; - package validator 负责发布物没有漂移。 做到这些,`webnovel-writer` 才会真正具备优秀 Claude Code 插件的工程稳定性。