dsh-maoying 0.1.19 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -16,7 +16,7 @@ Once installed, the main agent becomes the **editor-in-chief of your novel**: it
16
16
  - **Context on demand**: the chief reads index.yml for the big picture, then pulls only what the chapter at hand needs (previous chapter's ending ≈1500 chars + its outline + on-stage character cards + active foreshadow excerpts) — never the whole book.
17
17
  - **Narrow tool surface**: the chief sees only "role delegation + internal retrieval + coordination"; helpers carry their line's tools (reviewer read-only, researcher web+notes only) — less per-request tool overhead and context weight.
18
18
  - **Research**: the research helper searches the web for historical/geographic/domain material, files notes under `novel/research/`, separating fact from common lore from legend, with sources — a dividend of the DSH architecture.
19
- - **Creator panel**: a full-page web panel from the DSH sidebar — Overview (with in-place manuscript metadata editing and volume plan) / Chapters / Characters / Foreshadowing / Relations / Timeline / Worldbuilding / Style / Index Board, nine tabs; full-page chapter reading (outline side-by-side + manuscript/outline editing with save + five-dimension fields + status flow), form-based project.yml editing, style baseline viewing & editing (created from the default baseline when missing), UI language (中文/English), six font-size steps, and automatic new-version detection.
19
+ - **Creator panel**: a full-page web panel from the DSH sidebar — Overview (with in-place manuscript metadata editing and volume plan) / Chapters / Characters / Foreshadowing / Relations / Timeline / Worldbuilding / Style / Index Board, nine tabs; full-page chapter reading (outline side-by-side + manuscript/outline editing with save + five-dimension fields + status flow), form-based project.yml editing, style baseline viewing & editing (created from the default baseline when missing), human-editable source-file surfaces for ledgers and entity cards (edit/create/delete with structural validation and confirm dialogs), UI language (中文/English), six font-size steps, and automatic new-version detection.
20
20
  - **CLI fallback**: `maoying init / stats / index / export / brief / check` — six zero-dependency commands for scaffolding, stats, index rebuild, export, per-chapter writing cards and static checks.
21
21
 
22
22
  ## Quick Start
@@ -59,13 +59,13 @@ The chief aligns the setting with you item by item (genre, golden finger, tone,
59
59
 
60
60
  > Can we start chapter 3?
61
61
 
62
- The chief runs the continuity check, has the outliner produce the chapter outline (with the five narrative dimensions), and after your sign-off sends it to the writer, then the reviewer (checklist + four-dimension consistency scan); issues go back to the writer; once accepted, the lore keeper does finalization upkeep — you only call the shots at decision points.
62
+ The chief runs the continuity check, has the outliner produce the chapter outline (with the five narrative dimensions), and after your sign-off sends it to the writer, then the reviewer (checklist + consistency scan: conflicts / timeline / foreshadowing / settings plus the six coherence dimensions — behavior / causality / resources / identity / injuries / combat power); issues go back to the writer; once passing, the lore keeper runs finalization upkeep as one atomic pass (outline cross-check + five ledgers + index rebuild + consistency sweep — accepted only when everything is on disk) — you only call the shots at decision points.
63
63
 
64
64
  **Consistency pass**:
65
65
 
66
66
  > Run a consistency check over the first 20 chapters.
67
67
 
68
- The chief advances the phase to consistency; the reviewer scans four dimensions — conflicts / timeline / foreshadowing / settings — and returns issues ranked by severity.
68
+ The chief advances the phase to consistency; the reviewer scans conflicts / timeline / foreshadowing / settings plus the six coherence dimensions (behavior / causality / resources / identity / injuries / combat power) and returns issues ranked by severity.
69
69
 
70
70
  A reply of "ok / sure / go on" counts as confirmation; the chief advances directly without echoing it back.
71
71
 
@@ -74,10 +74,11 @@ A reply of "ok / sure / go on" counts as confirmation; the chief advances direct
74
74
  Open "**毛颖创作台**" at the bottom of the DSH sidebar — a full-page cockpit for the human eye, beyond what agents do:
75
75
 
76
76
  - **Chapters**: status filters + the writing queue; click a chapter for full-page reading — back button, outline side-by-side (Markdown rendered), in-place editing with save for the manuscript and the outline (textarea with manual save; if the file was changed externally while editing, saving is rejected and the latest content restored, never overwriting manual edits), five narrative-dimension fields, one-click status flow.
77
- - **Overview**: the "Edit" button on the manuscript card expands form-based editing of project.yml — title / author / genre / planned length / language / workflow phase / co-writing mode / synopsis (the former "Novel Settings" tab, merged in); saving preserves the file's existing comments. If project.yml was changed externally after the form loaded (manual edits or an agent advancing the phase), saving is rejected with a prompt to re-edit from the latest content instead of overwriting. A separate "Volume plan" card lists each volume's positioning and planned chapter range from volumes.yml — signed-off volume plans are visible in the panel.
77
+ - **Overview**: the "Edit" button on the manuscript card expands form-based editing of project.yml — title / author / genre / planned length / language / workflow phase / co-writing mode / synopsis (the former "Novel Settings" tab, merged in); saving preserves the file's existing comments. If project.yml was changed externally after the form loaded (manual edits or an agent advancing the phase), saving is rejected with a prompt to re-edit from the latest content instead of overwriting. A separate "Volume plan" card lists each volume's positioning and planned chapter range from volumes.yml — signed-off volume plans are visible in the panel, and its header offers "Edit source file" for whole-file editing of volumes.yml.
78
+ - **Managed-file surfaces**: character / worldbuilding / science cards and the six ledgers (relations / timeline / memories / clue board / foreshadows / volumes) can all be edited from the panel — "New" on the wall header, "Edit source file" / "Delete file" on card details, "Edit source file" on each ledger card head (empty timelines and relations graphs keep the entry too); saving runs structural validation (ledgers must parse as entry arrays, entity cards must carry frontmatter fences — anything else is rejected), and external-change protection matches the prose editor; the chapter reader can create an outline (pre-filled with the five-part skeleton), delete the outline, and delete the chapter — deletions always go through a confirm dialog: irreversible, recovery is via git, and the static check will flag orphaned references.
78
79
  - **Top bar**: current version always visible; a "new version ↗" badge links to the release page when npm has a newer one, next to an "Upgrade now" button that installs the latest release into the current DSH profile with pnpm (profile-directory installs only, with an automatic corepack fallback when pnpm is missing; when a global `maoying` CLI is detected it is updated to the same exact version, and skipped if absent; a DeepSeek restart is required to take effect); the gear opens Settings — UI language (中文/English), six font-size steps (100%–150%), all applied immediately and remembered.
79
80
 
80
- The panel writes state (chapter status, project.yml, index.yml rebuilds) and offers prose/outline editing to humans only (hash-based stale-write detection — external changes are never overwritten); the agent boundary is unchanged: in co-writing, prose belongs to the author and the chief.
81
+ The panel writes state (chapter status, project.yml, index.yml rebuilds), and every human editing entry — prose, outlines, ledgers, entity cards — is for humans only (hash-based stale-write detection plus structural validation; external changes are never overwritten); the agent boundary is unchanged: in co-writing, prose belongs to the author and the chief.
81
82
 
82
83
  ## Co-writing Mode (Author Writes)
83
84
 
@@ -89,7 +90,7 @@ The author-draft loop — you just write, hand it over, and the chores are taken
89
90
 
90
91
  After receiving a manuscript you get three things: a **review checklist** (issues only, no rewriting — applying them is up to you), a **ledger backfill** (foreshadowing / timeline / relations / memory / clue board recorded from what your text actually does, even off-plan changes, tagged `backfill`), and the **next chapter outline** (`novel/outlines/vXX-cXXX.md`, ready to write from).
91
92
 
92
- Companion commands: `maoying brief <dir> <chapter>` packs a per-chapter writing card (outline + previous ending + character cards + active foreshadowing — carry it to any editor or AI), and `maoying check <dir>` runs a zero-model static check (frontmatter completeness, foreshadow chapter references, timeline ordering, phase readiness gates — no model calls; LLM review goes through the chief).
93
+ Companion commands: `maoying brief <dir> <chapter>` packs a per-chapter writing card (outline + previous ending + character cards + active foreshadowing — carry it to any editor or AI), and `maoying check <dir>` runs a zero-model static check (frontmatter completeness, foreshadow chapter refs & staleness, outline hook section, timeline ordering, AI-flavor stats (repeated openers / metaphor density / sentence-length flatness), phase readiness gates — no model calls; LLM review goes through the chief).
93
94
 
94
95
  ## Methodology Skills
95
96
 
@@ -124,7 +125,7 @@ maoying stats [dir] # per-chapter CJK counts, status breakdown, current phase
124
125
  maoying index [dir] # rebuild index.yml from volumes.yml + chapters/ (derived file)
125
126
  maoying export [dir] # export the book: --format md|txt|epub (default md), --out <dir> to change destination
126
127
  maoying brief [dir] <chapter> # pack a per-chapter writing card (outline + previous ending + character cards + active foreshadowing); --out to write to disk, stdout by default
127
- maoying check [dir] # static check (no model calls): frontmatter / enums / chapter numbers / foreshadow refs / timeline years / relation-card refs / phase readiness gates
128
+ maoying check [dir] # static check (no model calls): frontmatter / enums / chapter numbers / foreshadow refs & staleness / outline hooks / AI-flavor stats / timeline years / relation-card refs / phase readiness gates
128
129
  ```
129
130
 
130
131
  Export examples:
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
  - **上下文按需取**:主编先读 index.yml 概览,写到哪章读哪章(前章结尾约 1500 字 + 该章大纲 + 出场角色卡 + 活跃伏笔节选),不把整本书塞进上下文。
17
17
  - **工具面收窄**:主编只见「角色委派 + 内部检索 + 协调」白名单,帮手各带本行工具(审校只读、考据只带联网+落笔记);每次请求的工具开销与上下文占用随之下降。
18
18
  - **素材考据**:research 帮手联网检索历史/地理/专业领域素材,笔记落 `novel/research/`,区分史实/通说/演义并附来源——DSH 架构的红利。
19
- - **创作台面板**:DSH 侧栏一键打开的全页可视化面板——概览(含书稿元信息编辑与分卷规划)/章节/角色/伏笔/关系图/时间线/设定/写作风格/索引板九个 tab;章节整页阅读(章纲对照 + 正文/章纲编辑保存 + 五维 + 状态流转)、project.yml 表单化编辑、写作风格查看与编辑(缺失时用默认基线创建)、顶栏字号六档缩放与自动新版检测。
19
+ - **创作台面板**:DSH 侧栏一键打开的全页可视化面板——概览(含书稿元信息编辑与分卷规划)/章节/角色/伏笔/关系图/时间线/设定/写作风格/索引板九个 tab;章节整页阅读(章纲对照 + 正文/章纲编辑保存 + 五维 + 状态流转)、project.yml 表单化编辑、写作风格查看与编辑(缺失时用默认基线创建)、账本与实体卡的人工编辑写面(编辑/新建/删除,带结构校验与确认弹层)、顶栏字号六档缩放与自动新版检测。
20
20
  - **CLI 兜底**:`maoying init / stats / index / export / brief / check` 六条零依赖命令管脚手架、统计、索引重建、导出、写作卡打包与静态体检。
21
21
 
22
22
  ## 快速开始
@@ -59,13 +59,13 @@ npm install -g dsh-maoying # 或装成全局 maoying 命令
59
59
 
60
60
  > 第三章可以开写了吗?
61
61
 
62
- 主编做衔接检查,委派大纲师出本章大纲(含五维叙事字段),过目后派写手写正文、审校审稿(清单 + 四维一致性扫描),有问题回写手修,通过后置 accepted 并委派设定管理员做定稿维护——你只需要在决策点拍板。
62
+ 主编做衔接检查,委派大纲师出本章大纲(含五维叙事字段),过目后派写手写正文、审校审稿(清单 + 一致性扫描:冲突/时间线/伏笔/设定 + 连贯六维:行为/因果/资源/身份/伤势/战力),有问题回写手修,通过后由设定管理员一次跑完定稿维护(章纲对照 + 五本账 + index 重建 + 一致性核对,全部落盘才置 accepted)——你只需要在决策点拍板。
63
63
 
64
64
  **集中审查**:
65
65
 
66
66
  > 前 20 章做一次一致性检查。
67
67
 
68
- 主编推进 phase 到 consistency,审校扫描冲突/时间线/伏笔/设定四维,问题按严重度排好交回写手。
68
+ 主编推进 phase 到 consistency,审校扫描冲突/时间线/伏笔/设定与连贯六维(行为/因果/资源/身份/伤势/战力),问题按严重度排好交回写手。
69
69
 
70
70
  用户回「ok / 可以 / 继续」即视为确认,主编直接推进,不复述确认。
71
71
 
@@ -74,10 +74,11 @@ npm install -g dsh-maoying # 或装成全局 maoying 命令
74
74
  DSH 左侧栏底部点「**毛颖创作台**」打开全页面板(改文件、跑流程之外,给肉眼看的驾驶舱):
75
75
 
76
76
  - **章节**:状态筛选 + 按单写作清单;点章节进整页阅读——返回按钮、章纲对照(Markdown 渲染)、正文与章纲就地编辑保存(textarea 手动保存;文件在编辑期间被外部改过时拒绝保存并放回磁盘最新内容,不覆盖人工改动)、五维叙事字段、一键状态流转。
77
- - **概览**:书稿卡右上「编辑」按钮展开 project.yml 的书名/作者/题材/篇幅/语言/工作流阶段/共创模式/简介表单化编辑(原「小说设置」tab 并入),保存保留文件里原有注释;表单载入后 project.yml 被外部(作者手改 / agent 推进阶段)改过时拒绝保存并提示重改,不覆盖人工改动。概览另设「分卷规划」卡,列出 volumes.yml 各卷定位与计划章节范围——拍板过的分卷有处可查。
77
+ - **概览**:书稿卡右上「编辑」按钮展开 project.yml 的书名/作者/题材/篇幅/语言/工作流阶段/共创模式/简介表单化编辑(原「小说设置」tab 并入),保存保留文件里原有注释;表单载入后 project.yml 被外部(作者手改 / agent 推进阶段)改过时拒绝保存并提示重改,不覆盖人工改动。概览另设「分卷规划」卡,列出 volumes.yml 各卷定位与计划章节范围——拍板过的分卷有处可查,卡头「编辑源文件」可整文件编辑 volumes.yml。
78
+ - **受管文件写面**:角色/设定/科学设定卡与六本账本(关系/时间线/记忆/线索板/伏笔/分卷)均可从面板编辑源文件——墙头「新建」、卡详情「编辑源文件/删除文件」、各账本卡头「编辑源文件」(时间线/关系图空态也给入口);保存时结构校验(账本须是条目数组、实体卡须带 frontmatter 围栏,不合即拒存),外部改动保护与正文编辑同口径;章节阅读页可新建章纲(本章目标/节拍/出场角色/需埋需收伏笔/与前章接口五件骨架预填)、删除章纲与删除章节——删除均确认弹层,不可逆,后悔靠 git,静态体检会把孤儿引用标出来。
78
79
  - **顶栏**:当前版本号常驻;npm 上有新版时亮「有新版 ↗」徽章直连发布页,旁边「一键升级」按钮直接用 pnpm 把最新包装进当前 DSH 档(仅支持 profile 目录安装,pnpm 缺失时自动回落 corepack;检测到全局 `maoying` CLI 时顺带以同一精确版本更新,未装则跳过;装完需重启 DeepSeek 才生效);齿轮打开系统设置,界面语言中文/English 可切、字号六档(100%–150%)整体缩放,均立即生效并记忆。
79
80
 
80
- 面板写状态(章节状态、project.yml、index.yml 重建),正文/章纲的编辑入口只给人用(hash 旧版检测,外部改动一律拒绝覆盖)——agent 的创作边界不变:共创模式下正文永远归作者与主编。
81
+ 面板写状态(章节状态、project.yml、index.yml 重建),正文/章纲/账本/实体卡等全部人工编辑入口只给人用(hash 旧版检测 + 结构校验,外部改动一律拒绝覆盖)——agent 的创作边界不变:共创模式下正文永远归作者与主编。
81
82
 
82
83
  ## 共创模式(作者亲笔)
83
84
 
@@ -89,7 +90,7 @@ author-draft 下的协作循环——你只管写,交稿即接管杂务:
89
90
 
90
91
  主编收稿后你会拿到三样东西:**审校意见清单**(只挑问题、不代改,改不改随你)、**账本回填**(伏笔/时间线/关系/记忆/线索五本账按你正文实际发生的记,计划外的改动也能认领,来源标 `backfill`)、**下一章章纲**(`novel/outlines/vXX-cXXX.md`,拿着就能写)。圣域纪律:`chapters/` 正文唯作者可改,agent 至多更新 frontmatter 的 summary 与五维字段,且先建议后动手。
91
92
 
92
- 配套命令:`maoying brief <dir> <章号>` 打包写作卡(章纲 + 前章结尾 + 角色卡 + 活跃伏笔,带去任意编辑器或其他 AI),`maoying check <dir>` 做零模型静态体检(frontmatter 完整性、伏笔章号引用、时间线乱序等,不调模型——LLM 审校走主编)。
93
+ 配套命令:`maoying brief <dir> <章号>` 打包写作卡(章纲 + 前章结尾 + 角色卡 + 活跃伏笔,带去任意编辑器或其他 AI),`maoying check <dir>` 做零模型静态体检(frontmatter 完整性、伏笔章号引用与超期、章纲钩子小节、时间线乱序、AI 味统计(句式重复/比喻密度/句长节奏)等,不调模型——LLM 审校走主编)。
93
94
 
94
95
  ## 方法论技能
95
96
 
@@ -111,7 +112,7 @@ rm -rf "${DSH_HOME:-$HOME/.dsh}/skills/"maoying-*
111
112
 
112
113
  ## novel/ 数据规范
113
114
 
114
- `novel/` 目录是整个插件的数据库:project.yml(元信息与七阶段 phase)、style.md(写作风格基准)、volumes.yml、chapters/(frontmatter 五维叙事字段 + 正文)、characters/(角色卡)、world/、science/(三色设定)、relations.yml、foreshadows.yml(伏笔状态机)、timeline.yml、memories.yml(含出场记录与承诺账)、clue-board.yml、research/、exports/。全部格式、示例与设计理由见:
115
+ `novel/` 目录是整个插件的数据库:project.yml(元信息与七阶段 phase)、style.md(写作风格基准)、volumes.yml、chapters/(frontmatter 五维叙事字段 + 正文)、characters/(角色卡)、world/、science/(三色设定)、relations.yml、foreshadows.yml(伏笔状态机)、timeline.yml、memories.yml(出场记录、承诺账、卷级梗概)、clue-board.yml、research/、exports/。全部格式、示例与设计理由见:
115
116
 
116
117
  - 速查版:项目初始化后的 `novel/README.md`(模板源 [templates/novel/README.md](templates/novel/README.md))
117
118
  - 完整版:[docs/spec.md](docs/spec.md)(为什么不用 SQLite、五维字段定义、伏笔状态机语义、出场记录约定)
@@ -124,7 +125,7 @@ maoying stats [dir] # 逐章 CJK 字数、状态分布、当前 phase
124
125
  maoying index [dir] # 从 volumes.yml + chapters/ 重建 index.yml(派生文件)
125
126
  maoying export [dir] # 导出全书:--format md|txt|epub(默认 md),--out <目录> 改输出位置
126
127
  maoying brief [dir] <chapter> # 组装单章写作卡(章纲+前章结尾+角色卡+活跃伏笔);--out 落盘,缺省 stdout
127
- maoying check [dir] # 静态体检(不调模型):frontmatter/枚举/章号/伏笔引用/时间线年份/关系卡引用/phase 就绪判据
128
+ maoying check [dir] # 静态体检(不调模型):frontmatter/枚举/章号/伏笔引用与超期/章纲钩子/AI 味统计/时间线年份/关系卡引用/phase 就绪判据
128
129
  ```
129
130
 
130
131
  export 示例:
package/bin/maoying.mjs CHANGED
@@ -12,7 +12,7 @@
12
12
  * maoying export [dir] 导出全书:--format md|txt|epub(默认 md)、--out <目录>
13
13
  * maoying brief [dir] <chapter> [--out <文件>]
14
14
  * 组装某章写作卡(章纲+前章结尾+出场角色卡+活跃伏笔)
15
- * maoying check [dir] 静态体检(不调模型):frontmatter/枚举/章号/伏笔引用/阶段就绪判据等
15
+ * maoying check [dir] 静态体检(不调模型):frontmatter/枚举/章号/伏笔引用/伏笔超期/章纲钩子/AI 味统计/阶段就绪判据等
16
16
  *
17
17
  * 子命令出错 exit 1,中文报错。
18
18
  */
@@ -446,7 +446,7 @@ const HELP_TEXT = `毛颖(maoying)—— 网文创作项目 CLI
446
446
  maoying export [dir] 导出全书:--format md|txt|epub(默认 md),--out <目录> 改输出位置
447
447
  maoying brief [dir] <chapter>
448
448
  组装某章写作卡(章纲+前章结尾+出场角色卡+活跃伏笔);--out <文件> 落盘,缺省打到 stdout
449
- maoying check [dir] 静态体检(不调模型):frontmatter 完整性、枚举值、章号卷号一致、伏笔章号引用、时间线年份、关系卡引用、phase 阶段就绪判据
449
+ maoying check [dir] 静态体检(不调模型):frontmatter 完整性、枚举值、章号卷号一致、伏笔章号引用、伏笔超期、章纲钩子、时间线年份、关系卡引用、AI 味统计、phase 阶段就绪判据
450
450
 
451
451
  说明:
452
452
  novel/ 目录的数据规范见 templates/novel/README.md(或项目内 novel/README.md)。
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 0. 定位与边界
6
6
 
7
- 面板管**可视化、状态,以及作者本人的稿件编辑**:小说内容的生产仍归主编(agent)与作者在编辑器/共创流程里协作,面板负责「一眼看清全局 + 状态快捷流转」,同时给作者本人一个带护栏的正文/章纲编辑入口(textarea + 手动保存 + hash 旧版检测,见 §2 的 `chapter-save` / `outline-save`)。agent 的创作边界不变:共创模式下 agent 依旧不得碰 author 章节的正文(spec §作者稿圣域)——面板编辑是**人**用的刀,不是给 agent 开的新通道。
7
+ 面板管**可视化、状态,以及作者本人的稿件编辑**:小说内容的生产仍归主编(agent)与作者在编辑器/共创流程里协作,面板负责「一眼看清全局 + 状态快捷流转」,同时给作者本人一个带护栏的正文/章纲编辑入口(textarea + 手动保存 + hash 旧版检测,见 §2 的 `chapter-save` / `outline-save`)。0.1.20 起(§4.1「全量可编辑写面」)六本账本 yml、四目录实体卡 md 与章纲新建也开放人工编辑,编辑纪律统一为「保存时结构校验(解析失败/缺围栏 422 拒存)+ 保存后语义体检(`check`)+ git 回滚兜底」——语义规则(状态机、必填章号等)是 agent 纪律不是人工禁区,但写面只服务人。agent 的创作边界不变:共创模式下 agent 依旧不得碰 author 章节的正文(spec §作者稿圣域)——面板编辑是**人**用的刀,不是给 agent 开的新通道。
8
8
 
9
9
  ## 1. 包接线(单包形态,不建子包)
10
10
 
@@ -54,10 +54,25 @@ webServer.register({ kind: 'prefix', path: '/api/maoying', handler: async (req,
54
54
  | `project-save` | POST | `{ path, values, base_hash? }`(values 为 8 平键 title/author/genre/length/language/phase/mode/description;base_hash 为表单载入时的 project.yml 指纹,即快照 `project_hash`) | `{ ok, project_hash }`——mutateProject 逐键改写保行尾注释、缺键按模板补齐;phase/mode 越枚举与空书名 422;base_hash 与写入前现读原文不一致 → 409「外部修改冲突」拒写不落盘(人工改动保护:表单载入后文件被作者/agent 改过即拒绝静默覆盖;缺省 base_hash 跳过检查,兼容旧调用方)。project_hash 为写后新指纹,客户端可作下一轮基线 |
55
55
  | `style-save` | POST | `{ path, text, base_hash? }`(text 为 style.md 全文;base_hash 为编辑器载入时的 style.md 指纹,即 `style` 路由的 `hash`) | `{ ok, hash }`——style.md 整文件覆写:纯 markdown 基准文档、无行级键位可言,整文件替换即最小手术(写前读、原子写,与 agent 的写法兼容);text 非 string 422,空文本允许保存(空文件 = 无基准,agent 侧优雅降级);base_hash 与写入前现读原文不一致 → 409「外部修改冲突」拒写不落盘(人工改动保护,与 project-save 同口径;文件不存在且带 base_hash 同样 409;缺省 base_hash 跳过检查 = 创建路径)。hash 为写后新指纹,客户端作下一轮基线 |
56
56
  | `chapter-save` | POST | `{ path, file, body, base_hash? }`(file 为 chapters/ 下文件名;body 为正文全文;base_hash 为进入编辑态时 `chapter` 路由的 `hash`) | `{ ok, hash }`——正文整段替换:frontmatter 围栏(含闭合行)之前逐字节保留、围栏后整段替换(正文是自由形态文本,无行级键位可手术,整段替换即最小干预,对 git diff 的扰动天然只落在正文段内);body 非 string / 章节缺 frontmatter 围栏 422、章节不存在 404、穿越 403;正文末尾无换行补一个 `\n`;base_hash 与写入前现读原文不一致 → 409「章节文件已被外部修改…」拒写不落盘(人工改动保护,与 project-save 同口径;缺省 base_hash 跳过检查,兼容旧调用方)。hash 为写后新指纹,客户端作下一轮基线 |
57
- | `outline-save` | POST | `{ path, file, body, base_hash? }`(file 为章节文件名或 stem,目标恒为 outlines/ 下同 stem 章纲;body 为章纲全文;base_hash 为章纲载入时的指纹,即 `chapter` 路由的 `outline.hash`) | `{ ok, hash }`——章纲整文件替换:纯 markdown 无 frontmatter(spec §outlines),整文件替换即最小手术(与 style-save 同一判断);body 非 string / stem 不合 vXX-cXXX 规范 422、章纲不存在 404(面板不新建章纲文件)、穿越 403;base_hash 检测同上 → 409「章纲文件已被外部修改…」拒写不落盘。hash 为写后新指纹,客户端作下一轮基线 |
57
+ | `outline-save` | POST | `{ path, file, body, base_hash? }`(file 为章节文件名或 stem,目标恒为 outlines/ 下同 stem 章纲;body 为章纲全文;base_hash 为章纲载入时的指纹,即 `chapter` 路由的 `outline.hash`) | `{ ok, hash }`——章纲整文件替换:纯 markdown 无 frontmatter(spec §outlines),整文件替换即最小手术(与 style-save 同一判断);body 非 string / stem 不合 vXX-cXXX 规范 422、章纲不存在 404(本路由只覆写不新建,新建走 `file-create`)、穿越 403;base_hash 检测同上 → 409「章纲文件已被外部修改…」拒写不落盘。hash 为写后新指纹,客户端作下一轮基线 |
58
+ | `file-source` | GET | `path`, `rel`(受管白名单内的相对路径,见下表) | `{ ok, rel, text, hash }`——受管文件全文 + 原文 sha256 指纹(hash 为 `file-save` 的 `base_hash` 基线,读与指纹同刻同源);不存在 404、白名单外/穿越 403 |
59
+ | `file-save` | POST | `{ path, rel, text, base_hash? }`(text 为文件全文;base_hash 为编辑器载入时 `file-source` 的 `hash`) | `{ ok, rel, hash }`——受管文件整文件覆写:text 非 string 422、结构校验(`validateManagedText`:账本 yml 须解析为条目数组且条目全平键、md 实体卡须带成对围栏;校验先于基线检查)422、文件不存在 404(新建走 `file-create`)、base_hash 过期 → 409「`{rel}` 已被外部修改,请刷新后基于最新内容重改再存」拒写不落盘;尾无换行补一个 `\n`。hash 为写后新指纹 |
60
+ | `file-create` | POST | `{ path, rel, text }` | `{ ok, rel, hash }`——新建受管文件(新角色/设定/科学设定卡、新章纲骨架由客户端模板预填):已存在 409 先到先建绝不覆盖、结构校验同 `file-save`、目录缺席自动创建 |
61
+ | `file-delete` | POST | `{ path, rel }` | `{ ok, rel }`——删除受管文件(含 `chapters/` 章节文件——这是它唯一的通用写通道);不存在 404;服务端不做二次确认,UI 层强制确认弹层 |
58
62
  | `rebuild-index` | POST | `{ path }` | `{ ok, chapters }`——照 CLI index 同一逻辑重建 index.yml |
59
63
 
60
- 共 19 条。写操作全部「行级原地替换」:只在 frontmatter/目标 yml 的对应行上做字符串手术,写前读、写后校验(替换计数 ≠1 即 409 拒写并报错),不做整文件重排——把对 git diff 的扰动压到最小,也与 agent 的写法兼容。(`self-update` 是例外:它不碰小说文件,跑的是 pnpm 安装;`chapter-create` 是另一例外:它从章纲落一个全新章节文件,不动任何既有文件的字节;`style-save` 亦是例外:style.md 是纯 markdown 基准文档、无行级键位可言,整文件覆写就是它的最小手术,写前读、原子写;`chapter-save` 亦是例外:正文是自由形态文本,写原语是「frontmatter 围栏定位 + 围栏后整段替换」,围栏(含闭合行)之前逐字节保留;`outline-save` 同理:章纲纯 markdown,整文件替换。)
64
+ ### 受管文件白名单(file-* 四路由共用 `managedRelCheck`)
65
+
66
+ | rel | kind | 读 | 存 | 建 | 删 |
67
+ |---|---|---|---|---|---|
68
+ | `relations.yml` / `timeline.yml` / `memories.yml` / `clue-board.yml` / `foreshadows.yml` / `volumes.yml` | yml | ✓ | ✓ | — | — |
69
+ | `characters/<slug>.md` / `world/<slug>.md` / `science/<slug>.md` / `research/<slug>.md`(slug=`^[a-z0-9][a-z0-9-]*$`) | md | ✓ | ✓ | ✓ | ✓ |
70
+ | `outlines/<stem>.md`(stem 复用 chapterSortKey 的 vXX-cXXX) | outline | ✓ | ✓ | ✓(章纲新建) | ✓ |
71
+ | `chapters/<vXX-cXXX>.md` | chapter | —(走 `chapter`) | —(走 `chapter-save`) | —(走 `chapter-create`) | ✓ 仅删 |
72
+
73
+ 校验顺序:rel 形状(反斜杠/深层 403、slug/stem 422)→ 白名单外 403(`index.yml` / `project.yml` / `novel/style.md` 有意排除——前两者是核心配置走专用路由,style 有专用 tab)→ resolve 包含双保险(越界 403)。
74
+
75
+ 共 23 条。写操作全部「行级原地替换」:只在 frontmatter/目标 yml 的对应行上做字符串手术,写前读、写后校验(替换计数 ≠1 即 409 拒写并报错),不做整文件重排——把对 git diff 的扰动压到最小,也与 agent 的写法兼容。(`self-update` 是例外:它不碰小说文件,跑的是 pnpm 安装;`chapter-create` 是另一例外:它从章纲落一个全新章节文件,不动任何既有文件的字节;`style-save` 亦是例外:style.md 是纯 markdown 基准文档、无行级键位可言,整文件覆写就是它的最小手术,写前读、原子写;`chapter-save` 亦是例外:正文是自由形态文本,写原语是「frontmatter 围栏定位 + 围栏后整段替换」,围栏(含闭合行)之前逐字节保留;`outline-save` 同理:章纲纯 markdown,整文件替换。0.1.20 的 `file-save` / `file-create` 是最后一批例外:受管账本 yml 与实体卡 md 由人工整文件改写,结构校验(`validateManagedText`)守住「存得进、快照读得出」的形状底线,语义问题交保存后的 `check` 与 git 回滚兜底。)
61
76
 
62
77
  ### host-debug 端点(现场诊断)
63
78
 
@@ -111,19 +126,19 @@ webServer.register({ kind: 'prefix', path: '/api/maoying', handler: async (req,
111
126
  挂载:
112
127
  - 左侧栏底部动作位入口「毛颖创作台」(sidebar.footer.action 键控槽,ctx.effect 注入 + MutationObserver 自愈);
113
128
  - 会话中栏全页 overlay:`html[data-dsh-maoying-active]` 驱动,`dsh-panel-activate` 事件与 mnemon/taskboard/ssh 等全页面板互斥,点侧栏会话行自动关闭;
114
- - 顶部工作区选择器(workspaces 路由取数,hasNovel 的排前;无 novel 工作区显示引导卡:一句 `maoying init` 提示 + 复制按钮)。面板懒挂载、关闭不卸载,故每次打开都借 `dsh-panel-activate` 广播重拉一次 workspaces——外部新建/删除的工作区重开即见。
129
+ - 顶部工作区选择器(workspaces 路由取数,hasNovel 的排前;无 novel 工作区显示引导卡:一句 `maoying init` 提示 + 复制按钮)。面板懒挂载、关闭不卸载(React 状态全保留),故每次打开都借 `dsh-panel-activate` 广播三重重拉——workspaces(外部新建/删除的工作区重开即见)、整份 state 快照(CLI / agent 改动的章节与设定重开即最新,无需手点右上角刷新)、阅读页本章正文(经重开序号透传 ChapterReader 静默重拉;编辑中的草稿不受影响,仍只走 409 冲突重置路径)。
115
130
 
116
131
  九个 tab(顺序即默认排布):
117
132
 
118
- 1. **概览**:project 卡(书名大字 + 类型/篇幅/语言 pills + 阶段徽章 + 简介,卡右上「编辑」按钮展开书稿元信息表单——原「小说设置」tab 并入,见 §4.1「小说设置并入概览」条目);统计卡(总字数/章节数/状态分布条);最近更新(chapters 按 mtime 前 5);warnings 黄条;静态体检黄条(check 路由问题清单,见 §4.1「人工改动保护 + 静态体检黄条」(0.1.14)条目)。
119
- 2. **章节**:表格(卷-章/标题/状态徽章/字数/梗概),状态筛选 pills;表格上方「按单写作」区块——有章纲且 status=pending 的章按序列出(章纲节选 + 状态徽章),未建章的孤儿章纲照列(「未建章」徽章 + 「建章」一键:POST chapter-create 落 pending 空章并重拉快照;行点击开章纲全文弹层,0.1.15 起),共创模式的主工作清单;行点击开整页阅读视图(0.1.12 起替代原右侧抽屉——fixed 侧弹层会被 DSH 侧边栏遮挡):返回按钮 + GET chapter 正文 + 章纲对照栏(左右分栏或折叠段)+ 复制文件路径按钮 + 五维字段卡 + 状态流转按钮(当前态 → 下一态一键,pending→writing→review→accepted);正文与章纲对照栏均可就地编辑保存(textarea + 手动保存,POST chapter-save / outline-save 携 base_hash 409 人工改动检测——frontmatter 围栏逐字节保留,外部改动拒写并放回磁盘最新内容,0.1.19 起)。
120
- 3. **角色**:卡墙(姓名/role 徽章四色/年龄性别/性格一句/动机一行),点击看全卡(含 arc/markers/background)。
121
- 4. **伏笔**:四列看板(埋设/推进/已回收/弃用),卡片含 priority 色点(high 红/normal 灰/low 淡)、`source: backfill` 的「回填」小徽章(账本回填来的条目,区别于写前规划)、埋设章→预期回收章、notes 全文直显(0.1.10 去掉两行截断);卡片按钮:推进到下一状态(planted→progressing→resolved;abandoned 只能从看板拖不动、按钮给「弃用」)。列头计数。
122
- 5. **关系图**:canvas 力导向图——节点=角色(radius 随出场无关、固定 18px,名字 label 下方),边=relations(intensity 1-5 → 线宽 1-4px,type 标在边中点 hover 显示 description);拖拽节点、空白处滚轮缩放、双击复位;右上角 +/- 缩放按钮(钳制同滚轮 0.4-2.5)与全屏按钮(Fullscreen API 能力检测,不支持则不渲染;进入全屏走 ResizeObserver 自动重铺);intensity 缺省 3。角色多于 30 个时只画与 relations 相连的节点,其余进「未入图」列表。
123
- 6. **时间线**:垂直轴,importance 1-5 → 点大小/颜色深浅,year 左列右卡片。
124
- 7. **设定**:子 tab 三分区切换(世界观/科学设定/资料检索,各带条目计数,仅渲染当前激活分区)——world 按 category 分组列表;science 三色标签(known 绿/extrapolation 黄/hypothesis 紫,标签下 references 链接列表);research 逐条渲染,空态也常驻可切。
133
+ 1. **概览**:project 卡(书名大字 + 类型/篇幅/语言 pills + 阶段徽章 + 简介,卡右上「编辑」按钮展开书稿元信息表单——原「小说设置」tab 并入,见 §4.1「小说设置并入概览」条目);统计卡(总字数/章节数/状态分布条);最近更新(chapters 按 mtime 前 5);warnings 黄条;静态体检黄条(check 路由问题清单,见 §4.1「人工改动保护 + 静态体检黄条」(0.1.14)条目);分卷规划卡卡头「编辑源文件」(volumes.yml 整文件编辑弹层,0.1.20 写面)。
134
+ 2. **章节**:表格(卷-章/标题/状态徽章/字数/梗概),状态筛选 pills;表格上方「按单写作」区块——有章纲且 status=pending 的章按序列出(章纲节选 + 状态徽章),未建章的孤儿章纲照列(「未建章」徽章 + 「建章」一键:POST chapter-create 落 pending 空章并重拉快照;行点击开章纲全文弹层,0.1.15 起),共创模式的主工作清单;行点击开整页阅读视图(0.1.12 起替代原右侧抽屉——fixed 侧弹层会被 DSH 侧边栏遮挡):返回按钮 + GET chapter 正文 + 章纲对照栏(左右分栏或折叠段)+ 复制文件路径按钮 + 五维字段卡 + 状态流转按钮(当前态 → 下一态一键,pending→writing→review→accepted);正文与章纲对照栏均可就地编辑保存(textarea + 手动保存,POST chapter-save / outline-save 携 base_hash 409 人工改动检测——frontmatter 围栏逐字节保留,外部改动拒写并放回磁盘最新内容,0.1.19 起);0.1.20 写面:无章纲空态加「新建章纲」(outlines/<stem>.md 五件骨架预填)、章纲对照栏卡头「删除章纲」、阅读顶栏「删除章节」——后两者均确认弹层(不可逆,后悔靠 git,check 会标孤儿引用)。
135
+ 3. **角色**:卡墙(姓名/role 徽章四色/年龄性别/性格一句/动机一行),点击看全卡(含 arc/markers/background);0.1.20 写面:墙头「新建角色」(模板预填)+ 全卡弹层底部「编辑源文件/删除文件」。
136
+ 4. **伏笔**:四列看板(埋设/推进/已回收/弃用),卡片含 priority 色点(high 红/normal 灰/low 淡)、`source: backfill` 的「回填」小徽章(账本回填来的条目,区别于写前规划)、埋设章→预期回收章、notes 全文直显(0.1.10 去掉两行截断);卡片按钮:推进到下一状态(planted→progressing→resolved;abandoned 只能从看板拖不动、按钮给「弃用」)。列头计数;0.1.20 写面:卡头「编辑源文件」(foreshadows.yml)。
137
+ 5. **关系图**:canvas 力导向图——节点=角色(radius 随出场无关、固定 18px,名字 label 下方),边=relations(intensity 1-5 → 线宽 1-4px,type 标在边中点 hover 显示 description);节点按角色配色(0.1.20 起):主角 #f53f3f 红 / 配角 #165dff 蓝 / 反派 #1d2129 黑 / 龙套与未标注 #fadc19 黄(查表 miss 落 minor,全节点恒有色),拖拽固定态统一加粗描边;脚注带四色图例;拖拽节点、空白处滚轮缩放、双击复位;右上角 +/- 缩放按钮(钳制同滚轮 0.4-2.5)与全屏按钮(Fullscreen API 能力检测,不支持则不渲染;进入全屏走 ResizeObserver 自动重铺);intensity 缺省 3。角色多于 30 个时只画与 relations 相连的节点,其余进「未入图」列表。防重叠(0.1.20 起):节点最小间距 62 硬碰撞分离(含名字 label 纵向净空,力式斥力之上兜底,弹簧 rest 120→130 配合多留缝隙);边为二次曲线——按两侧空旷度选朝向(迟滞防抖)绕开途中节点,同一对角色的重复边偏移放大 + 交替朝向互相分开(type 标签随曲线移到 t=0.5 点);hover 命中按曲线几何采样。0.1.20 写面:卡头「编辑源文件」(relations.yml,空态同样给入口)。
138
+ 6. **时间线**:垂直轴,importance 1-5 → 点大小/颜色深浅,year 左列右卡片;0.1.20 写面:卡头「编辑源文件」(timeline.yml,空态同样给入口——账本空不等于不可编辑)。
139
+ 7. **设定**:子 tab 三分区切换(世界观/科学设定/资料检索,各带条目计数,仅渲染当前激活分区)——world 内多分类时二级子 tab 按 category 切换(每 tab 带条目计数,仅渲染激活分类;单分类/无分类平铺直出,见 §4.1「世界观分类二级子 tab」条目);science 三色标签(known 绿/extrapolation 黄/hypothesis 紫,标签下 references 链接列表);research 逐条渲染,空态也常驻可切;0.1.20 写面:world/science 组头「新建设定」(模板预填)+ 条目卡「编辑源文件/删除文件」,research 暂无写面入口(快照有卡,入口下轮再议)。
125
140
  8. **写作风格**:novel/style.md 写作风格基准的查看与编辑——视图态 MdView 渲染全文,卡头「编辑」进整文件编辑态(textarea + 取消/保存,保存 POST style-save 携 base_hash 409 人工改动保护,写后新指纹接下一轮基线);文件缺失时显示空态卡,可用插件内置默认基线一键预填创建(保存即落盘),空文本允许保存。
126
- 9. **索引板**:clues 按 kind 分组(线索/红鲱鱼/推理/疑问,resolved 划线置灰)+ memories 按 category 分组(promise 类高亮)。
141
+ 9. **索引板**:clues 按 kind 分组(线索/红鲱鱼/推理/疑问,resolved 划线置灰)+ memories 按 category 分组(promise 类高亮);0.1.20 写面:两卡头「编辑源文件」(clue-board.yml / memories.yml)。
127
142
 
128
143
  状态徽章色(全局统一):pending 灰 / writing 蓝 / review 橙 / accepted 绿;phase 七态沿用七色 pill。文案全中文、禁 emoji 图标(用 ui-primitives 图标或纯 CSS)。
129
144
 
@@ -149,7 +164,12 @@ webServer.register({ kind: 'prefix', path: '/api/maoying', handler: async (req,
149
164
  - **写作风格 tab**(0.1.19):novel/style.md 写作风格基准(0.1.18 落的数据文件与四角色加载纪律)在面板有了入口——设定与索引板之间新增「写作风格」tab:视图态 MdView 渲染全文,卡头「编辑」进整文件编辑态(textarea + 取消/保存;保存 POST `style-save` 携 base_hash,409 人工改动保护链路照 ProjectMetaForm——成功接写后新指纹防连续保存假冲突,409 重拉磁盘真值把编辑器原地重置、停留编辑态让用户自行取舍);文件缺失时空态卡「用默认基线创建」——插件模板(templates/novel/style.md)预填编辑态、保存即创建(模板读不到时按钮禁用);空文本允许保存(空文件 = 无基准,agent 侧优雅降级),挂载/换工作区按需拉取 GET `style`(请求序号防过期响应)。路由 15 → 17 条(style GET / style-save POST);I18N zh/en 各 243 → 250 条(tabs.style / style.note / style.editTip / style.empty / style.createFromTpl / style.loadFailed / toast.styleSaved);九个 tab。
150
165
  - **正文/章纲面板编辑**(0.1.19):作者本人直接在面板写章节正文与章纲——章节阅读页「编辑」进正文编辑态(textarea + 取消/保存,无自动保存),章纲对照栏卡头「编辑」进章纲编辑态;保存 POST `chapter-save` / `outline-save`:正文写原语是「frontmatter 围栏定位 + 围栏后整段替换」(正文自由形态无行级键位可手术,围栏含闭合行之前逐字节保留),章纲纯 markdown 整文件替换;`GET chapter` 出参补顶层 hash 与 outline.hash(保存响应接写后新指纹作下一轮基线,防连续保存假冲突),base_hash 与写入前现读不一致 → 409 拒写不落盘(人工改动保护链路照 StyleTab:草稿丢弃、重拉磁盘真值放回编辑器,正文末尾无换行自动补齐;缺围栏/坏 stem 422、章纲不存在 404——面板不新建章纲文件、穿越 403);切章自动退出编辑态清草稿,防 A 章文字写进 B 章。路由 17 → 19 条(chapter-save / outline-save POST);I18N zh/en 各 250 → 258 条(reader.edit / reader.editTip / reader.save / reader.bodyEditHint / outline.editTip / outline.editHint / toast.chapterSaved / toast.outlineSaved);顶栏副标题与 README 的「只读正文」边界声明同步改写(spec §作者稿圣域不变——面板编辑是给人用的刀,agent 的圣域规则原样)。
151
166
  - **设定 tab 改子 tab 展示**(0.1.19):设定 tab 内世界观/科学设定/资料检索三张卡从纵向堆叠改为子 tab 条切换(各带条目计数,仅渲染当前激活分区);research 空时原实现整卡隐藏,现子 tab 恒在、空态文案常驻可切。路由不变;I18N zh/en 各 258 → 260 条(world.researchEmpty / world.subTabsAria)。
167
+ - **重开面板即最新内容**(0.1.20):面板懒挂载、关闭不卸载,React 状态(快照 / 阅读页章节 / tab 位)跨开关全保留,而 state 原本只在 effectiveWs 变化时拉取——同工作区重开显示的是上次会话的旧快照,得手点右上角刷新。现每次打开借 `dsh-panel-activate` 广播(source 过滤不变)三重重拉:workspaces、整份 state 快照(`reload()`,有旧快照时不闪骨架、原地换血)、阅读页本章(PageShell 重开序号 `reopenSeq` 透传 ChapterReader,effect 按序号触发 `loadDetail(file, { silent: editing })`——编辑中 silent 不闪骨架不打断 textarea,阅读态换最新正文);首次打开广播早于挂载、mount effect 已覆盖首拉,语义不变。编辑草稿纪律不变:loadState 不碰草稿,正文/章纲草稿仍只在 409 冲突重置路径放回磁盘真值。纯前端,路由不变;I18N 不变。
168
+ - **关系图节点角色配色**(0.1.20):canvas 节点按角色卡 role 上色——主角 #f53f3f 红 / 配角 #165dff 蓝 / 反派 #1d2129 黑 / 龙套与未标注 #fadc19 黄(模块常量 NODE_ROLE_COLORS 映射,越枚举/缺省 role 查表 miss 落 minor——全节点恒有色);拖拽固定态=统一加粗 accent 描边(lineWidth 1.5 → 3,唯一固定指示,不再有半透明填充分支);脚注 help 文案旁新增四色图例(色点 + 角色名,复用 role.* 既有标签,龙套一并进图例);顺手删除无调用者的 toScreen(hitNode/hitEdge 走 toWorld,不受影响)。纯前端,路由不变;I18N 键数不变(relations.help zh/en 文案更新)。
169
+ - **关系图防重叠**(0.1.20):canvas 力导向图三处——①硬碰撞分离:step() 速度积分之后按最小间距 62(两节点半径 18×2 + 名字 label 纵向净空)做两轮位置级互推(固定/拖拽节点不动推对方、双固定跳过,位移不写回速度靠阻尼收敛),弹簧 rest 120→130 配合多留缝隙,节点永不压叠;②边改二次贝塞尔曲线:控制点垂直偏移随边长缩放钳 [12,28],draw 每帧按曲线两侧对无关节点的最小距离(9 点采样)比空旷度选朝向、另一侧明显更空(+12 世界像素)才翻转(side 挂边对象上迟滞防抖),同一对角色的重复边按 (a,b) 分组序号放大偏移并交替朝向互相分开,type 标签移到曲线 t=0.5 点;③hover 命中检测跟曲线几何走(二次贝塞尔 9 段折线近似,阈值仍 10 世界像素,edgeCtrl 与 draw 同源)。纯前端,路由不变;I18N 不变。注:边完全零交叉在数学上不总成立(非平面图),本改动目标是消除节点压叠、线穿节点、重复边重合与常见交叠,不保证零交叉。
152
170
  - **关系图工具角标**(0.1.19):关系图右上角新增工具条——+/- 缩放按钮(步进 ×1.25 / ÷1.25,钳制与滚轮同口径 0.4-2.5;React 按钮够不着绘图 effect 闭包里的 sim,经 zoomApiRef 桥调用,effect 清理时置 null 防旧闭包误触)与全屏切换按钮(Fullscreen API 能力检测——wrap 有 requestFullscreen/webkitRequestFullscreen 且 document.fullscreenEnabled 非假才渲染,否则不占位;监听 fullscreenchange/webkitfullscreenchange 同步「全屏/退出全屏」文案,浏览器 ESC 退出也跟上;进/出全屏 wrap 尺寸变化走既有 ResizeObserver 自动 resize 重铺 canvas,Chromium UA 全屏样式覆盖 480px 定高)。纯前端,路由不变;I18N zh/en 各 260 → 264 条(relations.zoomIn / zoomOut / fs / exitFs),relations.help 文案同步更新(提缩放按钮与右上角全屏)。
171
+ - **世界观分类二级子 tab**(0.1.20):设定 tab 世界观条目分区内部再进一层——原纵向分组列表(myt-listHead 分组头 + myt-worldGroup 堆叠)在 world 条目按 category(frontmatter 自由文本,缺省「未分类」)聚出**多个**分类时改为二级子 tab 条(复用 myt-subTabs/myt-subTab + myt-subTabsInner 修饰:字号/padding 收一号),每 tab 带条目计数、仅渲染激活分类的条目(条目 markup 不变);单分类或全部未分类时平铺直出,不出 tab 条也不出分组头,world 为空维持空态。激活分类记忆在组件 state(切走再切回不丢),快照重拉后所存分类已不存在时回落第一个。category 是数据文件自由文本,分组容器保持 Object.create(null) 防原型污染。纯前端,路由不变;I18N zh/en 各 264 → 265 条(world.catTabsAria)。
172
+ - **全量可编辑写面(0.1.20)**:面板剩余只读内容开放为人工可编辑——①路由 19 → 23 条:`file-source`(GET 原文+指纹)/`file-save`(POST 整文件覆写,base_hash 409 + 结构校验 422)/`file-create`(新建,已存在 409)/`file-delete`(删除,服务端不二次确认),四条共用 `managedRelCheck` 白名单(§2 受管文件白名单表):六个账本 yml 读/存、四个 md 实体目录读/存/建/删(slug=`^[a-z0-9][a-z0-9-]*$`)、outlines 读/存/建/删、chapters 仅删;`index.yml`/`project.yml`/`novel/style.md` 有意排除(各走专用路由/弹层)。②结构校验 `validateManagedText`:账本 yml 须解析为顶层数组且条目全为平键对象(快照会静默丢弃 null/裸标量/数组条/空对象条——存得进读不出等于丢数据,存时一并 422);md 实体卡只验围栏成对;回退解析与真 yaml 解析两条路同一结论(测试双口径断言)。③UI 九处入口:角色墙头「新建角色」+ 全卡弹层「编辑源文件/删除文件」;world/science 组头「新建设定」(模板预填 `---\ncategory: 地点\n---` / `---\nlabel: known\n---`)+ 条目卡编辑/删除;伏笔/关系图/时间线/索引板两卡卡头「编辑源文件」(时间线/关系图空态也给入口);概览分卷卡头「编辑源文件」(volumes.yml);章节阅读页无章纲空态「新建章纲」(五件骨架预填)+ 阅读顶栏「删除章节」+ 章纲卡头「删除章纲」(删除均确认弹层,文案点名不可逆、后悔靠 git、check 会标孤儿引用)。共用三弹层组件(SourceEditorModal 带请求序号防过期响应 / CreateFileModal slug 客户端预校 / ConfirmModal 在途禁双击)。research 快照有卡但 v1 无写面入口。I18N zh/en 各 265 → 294 条(src.* 20 + toast.fileSaved/fileCreated/fileDeleted + reader.createOutline/deleteChapter + outline.deleteBtn + char.createBtn + world.createBtn/createScienceBtn)。测试:panel-core 层 6 例(白名单矩阵/结构校验双口径/读存建删)+ 路由层 2 例(file-source、三态全链路)。
153
173
 
154
174
  ## 5. 验收基线
155
175
 
package/docs/design.md CHANGED
@@ -70,9 +70,9 @@ dsh-maoying/
70
70
  | 伏笔状态机 | foreshadows.yml(planted/progressing/resolved/abandoned + 预期回收章节 + 优先级) | 文件规范 |
71
71
  | 时间线 / 叙事记忆(promise)/ 线索板 | timeline.yml / memories.yml / clue-board.yml | 文件规范 |
72
72
  | 人物关系图可视化 | relations.yml 纯数据(一期无图) | 文件规范 |
73
- | 上下文注入(全量角色+章节+伏笔) | 改为按需读:主编先读 index.yml 概览,写到哪章读哪章的上下文(前章结尾+该章大纲+出场角色卡+活跃伏笔) | 主编人设纪律 |
73
+ | 上下文注入(全量角色+章节+伏笔) | 改为分层门控按需读:常驻项(project/style/主角卡/金手指与核心冲突条目/活跃伏笔)恒读,其余角色卡与 world 条目写到谁读谁、长条目只读 `## 锚点` 段;主编先读 index.yml 概览,写到哪章读哪章的上下文(前章结尾+该章大纲+出场角色卡+活跃伏笔) | 主编人设纪律 |
74
74
  | AI 工具集 function calling | 天然消失(agent 直接用文件工具) | DSH 架构红利 |
75
- | 一致性检查(冲突/时间线/伏笔/设定) | review 角色(审校):四维扫描 + 审稿清单 | 委派角色 |
75
+ | 一致性检查(冲突/时间线/伏笔/设定 + 连贯六维) | review 角色(审校):一致性扫描 + 审稿清单 | 委派角色 |
76
76
  | 导出 EPUB/MD/TXT | **已交付**:`maoying export`(见 §8);HTML 从未规划 | CLI |
77
77
  | Token 用量统计 | 无需(DSH 自带) | — |
78
78
  | Web 管理面板 | **三期** | — |
@@ -91,7 +91,7 @@ novel/
91
91
  # 正文在 body。status: pending|writing|review|accepted
92
92
  characters/
93
93
  <slug>.md # frontmatter: name/age/gender/role(protagonist|antagonist|supporting|minor)/
94
- # appearance/personality/background/motivation/arc/markers[];body 为备注
94
+ # appearance/personality/background/motivation/arc/markers[]/可选 never_do[];body 为备注
95
95
  world/
96
96
  <slug>.md # frontmatter: category(地点|组织|概念|事件)/tags[];body 为描述
97
97
  science/
@@ -100,7 +100,7 @@ novel/
100
100
  foreshadows.yml # - {id: fs-001, title, status, priority, planted_chapter,
101
101
  # expected_resolve, resolved_chapter, notes}
102
102
  timeline.yml # - {year, title, description, importance: 1-5, chapter}
103
- memories.yml # - {category: character|location|item|event|promise|appearance|other,
103
+ memories.yml # - {category: character|location|item|event|promise|appearance|arc|other,
104
104
  # content, source_chapter}
105
105
  clue-board.yml # - {kind: clue|red-herring|deduction|question, content,
106
106
  # related_chapter, resolved: bool}
@@ -118,7 +118,7 @@ novel/
118
118
  |---|---|---|---|---|
119
119
  | outline | 大纲师 | 卷章规划、章节大纲+五维字段 | continuable | read read_image glob grep write edit bash ask_user_question todo_write |
120
120
  | write | 写手 | 章节正文(按大纲写、衔接前章、回报设定变更) | continuable | read read_image glob grep write edit bash ask_user_question todo_write |
121
- | review | 审校 | 审稿清单 + 四维一致性扫描(只读、出报告不改稿) | one-shot | read read_image glob grep todo_write ask_user_question |
121
+ | review | 审校 | 审稿清单 + 一致性扫描(冲突/时间线/伏笔/设定 + 连贯六维,只读、出报告不改稿) | one-shot | read read_image glob grep todo_write ask_user_question |
122
122
  | lore | 设定管理员 | 章节/角色/世界观/伏笔/时间线/记忆/线索板维护,出场记录与伏笔状态推进 | continuable | read glob grep write edit bash ask_user_question todo_write |
123
123
  | research | 素材调研员 | 联网考据(历史/地理/专业领域),笔记落 novel/research/ | one-shot | web_search web_fetch glob grep read write bash ask_user_question todo_write |
124
124
 
@@ -133,7 +133,7 @@ delegation-labels 静态角色名映射:{outline: 大纲师, write: 写手, re
133
133
  persona prefix 内容骨架(agent.cordis.yml 内联,中文书写):
134
134
 
135
135
  1. **身份**:网文主编/创作总监,管 project 目录 novel/,重活委派五帮手,自己只做规划、衔接、验收、状态推进。
136
- 2. **开工纪律**:先读 novel/project.yml + index.yml + style.md(若有);不确定文件格式读 novel/README.md;不全量读章节,写到哪章读哪章上下文(前章结尾 ~1500 字 + 该章 frontmatter + 出场角色卡 + 活跃伏笔节选)。
136
+ 2. **开工纪律**:先读 novel/project.yml + index.yml + style.md(若有);不确定文件格式读 novel/README.md;取上下文分层门控:常驻项恒读(project.yml/style.md/主角卡/金手指与核心冲突条目/活跃伏笔),按需项出场才读(其余角色卡与非核心 world 条目,长条目只读 `## 锚点` 段),跨卷剧情先读 memories.yml 的 arc 卷摘要;不全量读章节,写到哪章读哪章上下文(前章结尾 ~1500 字 + 该章 frontmatter + 按需角色卡 + 活跃伏笔节选)。
137
137
  3. **七阶段状态机**(每阶段推进写 project.yml phase):idea 选题 → setting 设定 → outline 大纲 → writing 写作 → review 审阅 → consistency 一致性 → export 导出。每完成一个里程碑必须推进 phase 并告知用户。
138
138
  4. **Writing 六步法**(逐章循环):
139
139
  ① 衔接检查:读前章结尾,确认无断裂;
@@ -141,14 +141,14 @@ persona prefix 内容骨架(agent.cordis.yml 内联,中文书写):
141
141
  ③ 委派 write 写正文(写手人设要求:按大纲覆盖五维、不写崩人设、章尾留钩子),status→writing;
142
142
  ④ 委派 review 审稿(清单:语言/节奏/人设符合/不剧透/伏笔推进合理/前后矛盾/风格符合),status→review;
143
143
  ⑤ 审稿问题回 write 修(continuable 就地续修)或主编微调;
144
- ⑥ 通过后 status→accepted,委派 lore 做定稿维护(出场记录、伏笔状态、记忆、线索板、时间线),`maoying index` 重建概览。
144
+ ⑥ 定稿维护(原子动作):委派 lore 一次跑完章纲对照结论(共创模式)+ 五本账(memories/timeline/relations/foreshadows/clue-board)+ `maoying index` 重建概览 + 一致性核对,全部落盘后 status→accepted;中途断了汇报缺口清单再续。
145
145
  循环检查:还有非 accepted 章节 → 回 ①。
146
146
  5. **Collab 四步共创**(新书冷启动):设定共创(最小设定集逐项对齐 + 世界观与核心角色卡落盘,设用户拍板点)→ 分卷规划(volumes.yml + 各卷 summary,设用户拍板点)→ 前三章交付(机械自检设定件齐备后走黄金三章:第一章立世界观钩子、第二章立主角动机、第三章立核心冲突)→ 交接循环写作(切 Writing 六步法)。
147
147
  6. **简短确认即执行(分级)**:逐章滚动中用户回「ok/可以/继续」直接推进下一步,不再复述确认;冷启动里程碑(设定共创、分卷规划)是方向性拍板点,须列决策点等用户实质回应。
148
148
  7. **设定变更上报**:写手回报的临场设定变更(新角色/新地点/伏笔异动)必须经 lore 落盘才算数;发现与既有设定冲突,先停笔报告主编。
149
149
  8. **失败处理**:委派失败按 DSH 委派 SOP(diagnose by stop reason,max-tokens 拆章,refusal 换路)。
150
150
 
151
- 各帮手 persona 一段话(内联在各委派行),写明本行工具纪律与回报格式(如 review 固定输出四维表格 + 清单勾选)。
151
+ 各帮手 persona 一段话(内联在各委派行),写明本行工具纪律与回报格式(如 review 固定输出一致性扫描表格(含连贯六维) + 清单勾选)。
152
152
 
153
153
  ## 6. 兼容面
154
154
 
@@ -190,7 +190,7 @@ project.yml 加 `mode` 字段:`ai-draft`(默认,现状)/ `co-write`(
190
190
 
191
191
  ### 9.3 章纲 outlines/
192
192
 
193
- `novel/outlines/vXX-cXXX.md`,**纯 markdown 无 frontmatter**(作者编辑器里打开不碍眼):本章目标、节拍、出场角色、需埋/需收伏笔、与前章接口。大纲师产物、作者创作输入、review 收稿时的对照基准。不入 index.yml,面板与 brief 现查现拼。
193
+ `novel/outlines/vXX-cXXX.md`,**纯 markdown 无 frontmatter**(作者编辑器里打开不碍眼):本章目标、节拍、出场角色、需埋/需收伏笔、与前章接口、章尾钩子(独立成 `## 钩子` 节:钩子类型 + 内容,类型对照 maoying-beat-pacing 钩子类型库)。大纲师产物、作者创作输入、review 收稿时的对照基准。不入 index.yml,面板与 brief 现查现拼。
194
194
 
195
195
  ### 9.4 账本回填(lore 收稿流程)
196
196
 
package/docs/spec.md CHANGED
@@ -10,7 +10,7 @@
10
10
  - **人机共读**。作者随时打开 foreshadows.yml 看账本、手改一个错字;数据库要做到同样的事得先写一层 UI 或 CLI——而文件天然免费。
11
11
  - **git 即版本控制**。整本书的历史就是目录的历史:哪一章改了什么、伏笔账本何时被谁推进,`git log -p` 一目了然;回滚一章就是回滚一个文件。SQLite 的 blob 历史在 git 里是噪音。
12
12
  - **零迁移零运维**。schema 演进 = 在 README 里补两行说明 + 旧文件照读;没有 migration 脚本,没有锁文件,没有「数据库被另一个进程占用」。
13
- - **上下文按需取**。主编不全量读章节:先读 index.yml 概览,写到哪章读哪章的上下文(前章结尾 + 该章 frontmatter + 出场角色卡 + 活跃伏笔节选)。文件粒度就是天然的上下文裁剪单元。
13
+ - **上下文按需取(分层门控)**。取上下文分两层:**常驻项**恒读——project.yml、style.md、主角卡、金手指与核心冲突的 world 条目、活跃伏笔;**按需项**出场/涉及时才读——其余角色卡与非核心 world 条目,写到哪章读哪章;长条目(>100 行)不整读,只读开头锚点段与相关小节(约定条目用 `## 锚点` 开头放 10 行内摘要,见速查版 world/ 说明)。在此之上主编不全量读章节:先读 index.yml 概览,写到哪章读哪章的上下文(前章结尾 + 该章 frontmatter + 按需角色卡 + 活跃伏笔节选)。文件粒度就是天然的上下文裁剪单元。
14
14
 
15
15
  什么时候该换数据库:多人同时写同一本书、单书章节数到千级、需要全文检索正文以外的高级查询。一期都不在诉求内。
16
16
 
@@ -20,6 +20,7 @@
20
20
  - **frontmatter 用 `---` 围栏**,键值一行一个、简单标量;正文(body)在第二个 `---` 之后。frontmatter 键名用英文(工具安全),值用中文。
21
21
  - **枚举一律全称**,见速查版「总原则」一节;新增枚举值属于规范变更,须同步本文与主编人设。
22
22
  - **index.yml 是派生文件**,任何手工改动都会被 `maoying index` 或 lore 角色覆盖。
23
+ - **人工可编辑写面(创作台面板)**:除派生的 index.yml 外全部数据文件人工可改——面板 file-* 通道对六个账本 yml(relations/timeline/memories/clue-board/foreshadows/volumes)、characters/world/science/research 实体卡 md、outlines、chapters 的删除开放整文件编辑。护栏是三道:保存时结构校验(账本须解析为条目数组且条目全平键、md 实体卡须带成对围栏,否则 422 拒存——「存得进、快照读不出」的条目一律不收)+ 保存后 `check` 静态体检标语义问题 + git 回滚兜底。语义规则(状态机、必填章号等)是 agent 纪律不是人工禁区;`project.yml` 的 `phase` 推进权仍只在主编。
23
24
  - 章节文件名 `v<卷号2位>-c<章号3位>.md`;frontmatter 的 `volume`/`num` 与文件名一致(CLI 与 index 重建以文件名为主键,frontmatter 为辅)。
24
25
 
25
26
  ## 2. 逐文件规范
@@ -47,15 +48,15 @@
47
48
  - 可选 `writer` 键(co-write 用):`author | ai`,记本章正文归谁写;缺省按 project.yml 的 `mode` 推——`author-draft` 下整本按 author、`ai-draft` 下整本按 ai。键只做记录与面板展示,状态机仍看 `status`。
48
49
 
49
50
  ### outlines/vXX-cXXX.md
50
- 章纲:共创模式(`co-write` / `author-draft`)下大纲师给作者的创作输入,与章节文件一一对应(`outlines/v01-c005.md` ↔ `chapters/v01-c005.md`)。**纯 markdown、无 frontmatter**——作者会在任意编辑器里打开它,`---` 围栏只会碍眼(第 1 节「frontmatter 用围栏」的总约束不适用本目录)。五件内容写全:本章目标、节拍(场景推进顺序与情绪起伏)、出场角色(谁上场、各带什么目的)、需埋/需收伏笔(对照 foreshadows.yml 报 id)、与前章接口(从哪个钩子接、结尾钩到哪)。颗粒度标准:作者拿着就能动笔,不写「参见大纲」式的空转。
51
+ 章纲:共创模式(`co-write` / `author-draft`)下大纲师给作者的创作输入,与章节文件一一对应(`outlines/v01-c005.md` ↔ `chapters/v01-c005.md`)。**纯 markdown、无 frontmatter**——作者会在任意编辑器里打开它,`---` 围栏只会碍眼(第 1 节「frontmatter 用围栏」的总约束不适用本目录)。六件内容写全:本章目标、节拍(场景推进顺序与情绪起伏)、出场角色(谁上场、各带什么目的)、需埋/需收伏笔(对照 foreshadows.yml 报 id)、与前章接口(从哪个钩子接)、章尾钩子——独立成 `## 钩子` 节(钩子类型 + 内容,类型对照 maoying-beat-pacing 的钩子类型库,写明下一章前提被什么改变)。颗粒度标准:作者拿着就能动笔,不写「参见大纲」式的空转。
51
52
 
52
53
  约定:章纲是计划不是章节事实,**不入 index.yml**(index 只索引章节实况),面板与 `maoying brief` 现查现拼。谁写谁读:大纲师写,作者读,review 收稿时对照评偏离——作者没照章纲写不算错,偏离如实报给主编裁决,账本永远跟正文走。
53
54
 
54
55
  ### characters/<slug>.md
55
- `role` 四态 `protagonist|antagonist|supporting|minor`。`markers`(辨识标记)是审校盯人设的抓手:口癖、习惯动作、禁忌。角色卡一经 `accepted` 章节引用,改动须过主编(写手发现需要新设定时上报,不得自行改卡)。
56
+ `role` 四态 `protagonist|antagonist|supporting|minor`。`markers`(辨识标记)是审校盯人设的抓手:口癖、习惯动作、禁忌。可选 `never_do`(字符串数组)是行为红线——此角色绝不会做的事(如「绝不当众认输」「从不撒谎害人」);写手落笔前过一遍,审校对出场角色逐条对照,越线即 P0(口径见审校清单技能人设层)。角色卡一经 `accepted` 章节引用,改动须过主编(写手发现需要新设定时上报,不得自行改卡)。
56
57
 
57
58
  ### world/<slug>.md
58
- `category` 用中文四类 `地点|组织|概念|事件`(值是给人和 agent 读的,中文检索更直接);`tags` 供 grep 圈定范围。
59
+ `category` 用中文四类 `地点|组织|概念|事件`(值是给人和 agent 读的,中文检索更直接);`tags` 供 grep 圈定范围。长条目(>100 行)建议以 `## 锚点` 段开头——10 行内摘要(这是什么、规则边界、与主线的关系),供分层取上下文只读锚点段与相关小节。
59
60
 
60
61
  ### science/<slug>.md
61
62
  三色标注:`known`(史实/公理,写了不算错)→ `extrapolation`(从 known 合理推演,读者能接受)→ `hypothesis`(自设假说,全书内部自洽即可)。审校的「设定一致性」扫描以此分级裁判:违反 known 是硬伤,hypothesis 之间打架按主编裁决。`references` 指向依赖的其他设定 id 或现实出处,形成可追溯的设定依赖链。
@@ -89,6 +90,8 @@ planted ──→ progressing ──→ resolved
89
90
 
90
91
  - **出场记录**:`category: appearance`,一章一条记「谁在哪章登场」;主角每章都记(审校查隐身主角),配角记首次登场与关键回场;
91
92
  - **承诺**:`category: promise`,角色说出口的承诺逐条记账——读者记得每一句「我一定会回来」,审校查兑现;
93
+ - **卷级梗概**:`category: arc`,一卷一条,卷末由 lore 从本卷正文与账本凝固——写定不再重写,下一卷另起新条;
94
+ - **三层冻结摘要**:章级摘要 = 章节 frontmatter `summary`(`accepted` 后冻结不重写)、卷级摘要 = 本条 `arc`、全书概览 = index.yml(派生重建)——上下文恢复时卷摘要优先、章级细节补差,禁止滚动重写大摘要;
92
95
  - 只记已写进正文的事实;计划中的事记在章节 frontmatter 或 foreshadows.yml,不进记忆;
93
96
  - 不改动既有条目(写错了由主编裁决后修正,留 notes 说明)。
94
97
 
@@ -103,6 +106,8 @@ planted ──→ progressing ──→ resolved
103
106
 
104
107
  收稿循环(author-draft / co-write 的 author 章):作者交稿 → review 出意见清单 → lore 按正文回填五本账(foreshadows / timeline / relations / memories / clue-board)并重建 index.yml → 主编向作者汇报本章伏笔/时间线/关系变动 → 大纲师出下一章章纲。
105
108
 
109
+ Writing 六步法的第⑥步定稿维护是**原子动作**:章纲对照结论(共创模式)+ 五本账(memories / timeline / relations / foreshadows / clue-board)+ index.yml 重建 + 一致性核对一次跑完,全部落盘才算定稿(status 才置 `accepted`);中途断了必须汇报缺口清单(列明哪几项未落盘)再续跑,不许带半套账定稿。
110
+
106
111
  使用约定:`novel/` 建议纳入 git——账本变动看 diff,lore 回填动了哪条一目了然;作者对某笔回填不认可,`git checkout` 对应文件即是回滚。
107
112
 
108
113
  ## 3. index.yml(派生)
@@ -134,6 +139,6 @@ total: {chapters: 21, words: 65210, accepted: 18}
134
139
  - `maoying index` 是第 3 节重建逻辑的人工兜底(主编的日常路径是让 lore 角色直接重建);
135
140
  - `maoying export [dir]` 导出全书为 md / txt / epub(默认 md;`--out` 改输出目录,缺省 `<dir>/exports/`);
136
141
  - `maoying brief [dir] <chapter>` 组装单章写作卡(章纲 + 前章结尾 + 出场角色卡 + 活跃伏笔);`--out <文件>` 落盘,缺省打到 stdout;
137
- - `maoying check [dir]` 静态体检(不调模型):frontmatter 完整性、枚举值(含 phase)、章号卷号一致、伏笔章号引用、时间线年份、关系卡引用,并把本节 phase 完成判据落成静态检查——phase 到 outline 及之后仍缺主角卡/核心反派卡/世界观条目/分卷规划,或有两张及以上角色卡而 relations.yml 为空,即报 error(判据不满足回上一阶段补齐)。
142
+ - `maoying check [dir]` 静态体检(不调模型):frontmatter 完整性、枚举值(含 phase)、章号卷号一致、伏笔章号引用、伏笔超期未推进(planted 超 30 章无进展即 warn)、章纲钩子小节缺失、时间线年份、关系卡引用、AI 味统计(连续同式开头/比喻词密度/句长波动,命中即 warn),并把本节 phase 完成判据落成静态检查——phase 到 outline 及之后仍缺主角卡/核心反派卡/世界观条目/分卷规划,或有两张及以上角色卡而 relations.yml 为空,即报 error(判据不满足回上一阶段补齐)。
138
143
 
139
144
  六者都零依赖,解析器只认本规范的两类形态(平键映射、顶层数组);深度嵌套不在支持范围——这是规范约束的执行手段之一。
package/index.mjs CHANGED
@@ -64,6 +64,8 @@ import { fileURLToPath } from 'node:url'
64
64
 
65
65
  import {
66
66
  createChapterFromOutline,
67
+ createManagedFile,
68
+ deleteManagedFile,
67
69
  listWorkspaces,
68
70
  mutateChapterBody,
69
71
  mutateChapterStatus,
@@ -73,10 +75,12 @@ import {
73
75
  mutateProject,
74
76
  parseStateSnapshot,
75
77
  readChapter,
78
+ readManagedFile,
76
79
  readOutlineFile,
77
80
  readStyleState,
78
81
  rebuildIndex,
79
82
  resolveNovelRoot,
83
+ saveManagedFile,
80
84
  saveStyleText,
81
85
  } from './lib/panel-core.mjs'
82
86
  // 静态体检(check 路由)与 CLI check 同源:直接复用 novel-parse 的检查器。
@@ -946,7 +950,7 @@ export async function registerPrefixRouteWithRetry(webServer, route, { attempts
946
950
  }
947
951
 
948
952
  /**
949
- * 注册创作台全部路由(docs/creator-panel.md §2 的 19 条)。返回宿主 disposer;
953
+ * 注册创作台全部路由(docs/creator-panel.md §2 的 23 条)。返回宿主 disposer;
950
954
  * webServer 缺席(非 web 部署)时抛错,由 apply 侧统一降级为 warn。
951
955
  */
952
956
  export async function registerCreatorRoutes(ctx) {
@@ -1204,6 +1208,43 @@ export async function registerCreatorRoutes(ctx) {
1204
1208
  return
1205
1209
  }
1206
1210
 
1211
+ if (route === 'file-source' && req.method === 'GET') {
1212
+ // 受管文件读(0.1.20「全量可编辑写面」,四条通用路由之一):rel 白
1213
+ // 名单校验 + 结构口径在 panel-core(managedRelCheck / readManagedFile),
1214
+ // 路由只做围栏与分发。hash 为原文指纹——编辑态保存的 base_hash 基线。
1215
+ const novelDir = resolveNovelRoot(url.searchParams.get('path'), ctx.workspaceRegistry)
1216
+ json(res, 200, readManagedFile(novelDir, url.searchParams.get('rel')))
1217
+ return
1218
+ }
1219
+
1220
+ if (route === 'file-save' && req.method === 'POST') {
1221
+ // 受管文件存:整文件覆写 + 保存时结构校验(解析失败/缺围栏 422)+
1222
+ // base_hash 过期 409(人工改动保护,与 project-save 同口径文案)。
1223
+ const body = await readBody(req, res)
1224
+ const novelDir = resolveNovelRoot(body.path, ctx.workspaceRegistry)
1225
+ json(res, 200, saveManagedFile(novelDir, body.rel, body.text, { baseHash: body.base_hash }))
1226
+ return
1227
+ }
1228
+
1229
+ if (route === 'file-create' && req.method === 'POST') {
1230
+ // 受管文件建:已存在 409(绝不覆盖),结构校验同存(新角色卡/新章
1231
+ // 纲由客户端模板预填,服务端只验形状)。
1232
+ const body = await readBody(req, res)
1233
+ const novelDir = resolveNovelRoot(body.path, ctx.workspaceRegistry)
1234
+ json(res, 200, createManagedFile(novelDir, body.rel, body.text))
1235
+ return
1236
+ }
1237
+
1238
+ if (route === 'file-delete' && req.method === 'POST') {
1239
+ // 受管文件删:不可逆,服务端不做二次确认(UI 层强制确认弹层);
1240
+ // 白名单最严——账本 yml / md 实体卡 / outlines 之外只有 chapters/
1241
+ // 的删除(正文编辑走 chapter-save,通用存不开放防绕过状态机语义)。
1242
+ const body = await readBody(req, res)
1243
+ const novelDir = resolveNovelRoot(body.path, ctx.workspaceRegistry)
1244
+ json(res, 200, deleteManagedFile(novelDir, body.rel))
1245
+ return
1246
+ }
1247
+
1207
1248
  if (route === 'rebuild-index' && req.method === 'POST') {
1208
1249
  const body = await readBody(req, res)
1209
1250
  const novelDir = resolveNovelRoot(body.path, ctx.workspaceRegistry)
package/lib/base.css CHANGED
@@ -235,6 +235,10 @@ html[data-dsh-maoying-active]:not([data-dsh-mnemon-active]):not([data-dsh-taskbo
235
235
  font-weight: 600;
236
236
  }
237
237
  .myt-subTab .myt-boardCount { line-height: 16px; }
238
+ /* 二级分类 tab(设定 tab 内 world 分区按 category 再切):比一级子 tab 再小一号 */
239
+ .myt-subTabsInner { margin-top: -2px; }
240
+ .myt-subTabsInner .myt-subTab { font-size: 12px; line-height: 16px; padding: 3px 8px; border-radius: 6px; }
241
+ .myt-subTabsInner .myt-subTab .myt-boardCount { line-height: 14px; }
238
242
 
239
243
  /* ── 卡片 / 栅格 ───────────────────────────────────────────────────────── */
240
244
  .myt-card {
@@ -671,6 +675,17 @@ html[data-dsh-maoying-active]:not([data-dsh-mnemon-active]):not([data-dsh-taskbo
671
675
  .myt-modalHead { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 16px; border-bottom: 1px solid var(--dsw-alias-border-l1); }
672
676
  .myt-modalTitle { margin: 0; min-width: 0; font-size: 14px; line-height: 20px; font-weight: 600; color: var(--dsw-alias-label-primary); overflow-wrap: anywhere; }
673
677
  .myt-modalBody { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; }
678
+ /* ── 受管文件写面(0.2.x):源文件编辑/新建/删除确认三弹层 ────────────────
679
+ srcCard 比 modalCard 宽一档:整文件 textarea 是主角,宽度优先给代码文本。 */
680
+ .myt-srcCard { width: min(760px, 100%); }
681
+ .myt-srcRel { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; line-height: 16px; color: var(--dsw-alias-label-tertiary); overflow-wrap: anywhere; }
682
+ .myt-srcHint { font-size: 11px; line-height: 16px; }
683
+ .myt-srcArea { min-height: 46vh; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; line-height: 1.6; }
684
+ .myt-itemActions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
685
+ .myt-itemActions .myt-btn { padding: 2px 8px; font-size: 11px; line-height: 16px; }
686
+ .myt-confirmCard { width: min(460px, 100%); }
687
+ .myt-confirmText { font-size: 12px; line-height: 19px; color: var(--dsw-alias-label-secondary); overflow-wrap: anywhere; white-space: pre-wrap; }
688
+ .myt-outlineDelBtn { color: var(--dsw-alias-state-error-primary); }
674
689
  .myt-kvRow { display: flex; gap: 10px; font-size: 12px; line-height: 18px; }
675
690
  .myt-kvKey { flex: none; width: 64px; color: var(--dsw-alias-label-tertiary); }
676
691
  .myt-kvVal { min-width: 0; color: var(--dsw-alias-label-secondary); overflow-wrap: anywhere; white-space: pre-wrap; }
@@ -710,6 +725,15 @@ html[data-dsh-maoying-active]:not([data-dsh-mnemon-active]):not([data-dsh-taskbo
710
725
  }
711
726
  .myt-graphFoot { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; color: var(--dsw-alias-label-tertiary); font-size: 11px; }
712
727
 
728
+ /* ── 关系图角色图例:色点 + 角色名(canvas 内色同 NODE_ROLE_COLORS)──── */
729
+ .myt-graphLegend { display: inline-flex; align-items: center; gap: 10px; margin-left: auto; }
730
+ .myt-legendItem { display: inline-flex; align-items: center; gap: 4px; }
731
+ .myt-legendDot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
732
+ .myt-legendDot[data-role="protagonist"] { background: #f53f3f; }
733
+ .myt-legendDot[data-role="supporting"] { background: #165dff; }
734
+ .myt-legendDot[data-role="antagonist"] { background: #1d2129; border: 1px solid var(--dsw-alias-border-l4, var(--dsw-alias-border-l2)); }
735
+ .myt-legendDot[data-role="minor"] { background: #fadc19; border: 1px solid color-mix(in srgb, var(--dsw-alias-label-tertiary) 60%, transparent); }
736
+
713
737
  /* ── 关系图工具角标:+/- 缩放常驻;全屏按钮能力检测通过才渲染 ───────── */
714
738
  .myt-graphTools { position: absolute; top: 10px; right: 10px; display: flex; gap: 6px; z-index: 3; }
715
739
  .myt-graphTool {