|
|
@@ -0,0 +1,137 @@
|
|
|
+# 技术设计:M4 AI 角色层与一级宿主壳
|
|
|
+
|
|
|
+> 前置:已读 实施计划 §M4/§1.5、多智能体 spec v3.4、story-repo-spec 0.8 §8/§2.0/§10/§11、v6 reviewer.md + 知识抽样。
|
|
|
+> 落点全部在 `v7/`(包自包含);AI 协作层只吃 DTO、只吐结构化,落盘走 M2 Writer 小端口。
|
|
|
+
|
|
|
+## 1. 落点布局(v7/ 下,全绿地)
|
|
|
+
|
|
|
+```
|
|
|
+v7/
|
|
|
+├── roles/ # 角色单源(markdown + frontmatter),真源
|
|
|
+│ ├── 事实审查.md
|
|
|
+│ └── 编辑审.md
|
|
|
+├── skills/
|
|
|
+│ └── webnovel-writer/SKILL.md # 状态机单入口,平台条件块,真源
|
|
|
+├── references/ # 知识层平移(逐文件审查后入)
|
|
|
+│ ├── 题材模板/ 追读力/ 爽点节奏/
|
|
|
+│ └── 迁移报告.md
|
|
|
+├── adapters/
|
|
|
+│ ├── registry.json # 三级分级
|
|
|
+│ ├── claude-code/support.md
|
|
|
+│ └── codex/support.md
|
|
|
+├── templates/AGENTS.md # 工作目录公约数层模板(标记块)
|
|
|
+├── scripts/build-host-shells.mjs # 生成器 CLI(薄壳)
|
|
|
+└── src/
|
|
|
+ ├── review/ # 两审编排 Use Case(确定性,零真 AI)
|
|
|
+ │ ├── index.js # assembleReviewInput / runReviews / mergeReviews / persistReviewReport
|
|
|
+ │ └── schema.js # ReviewIssue 校验 + 阻断规则
|
|
|
+ ├── dto/ # 跨层稳定 DTO 组装器
|
|
|
+ │ ├── chapter-brief.js # ChapterBrief
|
|
|
+ │ └── character-context.js# CharacterContext
|
|
|
+ ├── session/index.js # readBooksRegistry / assembleSessionContext / scanRebuildBooks
|
|
|
+ ├── host-shells/generate.js # 生成器逻辑(可单测)+ drift check
|
|
|
+ └── state-machine/persist.js# AI 态产物回流落盘(序0/1/4/6)
|
|
|
+```
|
|
|
+
|
|
|
+**约定**(延续 M1-M3):`scripts/build-host-shells.mjs` 与 `bin/` 同为薄入口,逻辑在 `src/host-shells/`;命令走 `run(args,options,ctx)` 纯返回契约;零第三方依赖。
|
|
|
+
|
|
|
+## 2. 两审编排(R1,确定性核心)
|
|
|
+
|
|
|
+### 2.1 边界:JS 做编排,AI 做审稿
|
|
|
+v7 铁律:状态机/脚本不做业务判断,AI 吃 DTO 吐结构化。两审的"读整章找问题"是 AI 的活;JS 负责**组装输入 + 校验输出 + 合并落盘 + 诚实声明**。用**依赖注入**把 AI 隔在确定性层之外:
|
|
|
+
|
|
|
+```js
|
|
|
+// reviewers 由宿主壳接线(完整=两个 subagent;降级=主 agent 顺序);测试注入假函数→零真 AI
|
|
|
+runReviews(ctx, { chapterNum, draftPath, mode, reviewers })
|
|
|
+// 1. input = assembleReviewInput(...) // DTO,无文件路径
|
|
|
+// 2. fact = reviewers.factCheck(input) // AI 出 ReviewIssue[]
|
|
|
+// edit = reviewers.editorial(input) // mode='degraded' 时顺序
|
|
|
+// 3. validateReviewReport(fact|edit) // schema + 阻断规则
|
|
|
+// 4. merged = mergeReviews({fact,edit},{mode}) // 合并 + counts + 诚实声明
|
|
|
+// 5. persistReviewReport(...) // 落盘 工作区/审稿.md + 评审报告/
|
|
|
+```
|
|
|
+
|
|
|
+### 2.2 ReviewInput DTO(AI 不见路径)
|
|
|
+`{ 章号, 草稿全文, 本章要写到的事[], 全书近况片段, 相关角色:CharacterContext[], 相关条目(伏笔/悬念/感情线), 时间线片段, 信息差关键词候选[], 名册待确认新专名[] }`。全部经 M1 读接口 + M2 备料组装,值进 DTO,路径不进。
|
|
|
+
|
|
|
+### 2.3 ReviewIssue schema 与阻断规则(src/review/schema.js)
|
|
|
+- 字段:`severity / category / location / description / evidence / fix_hint / blocking`。
|
|
|
+- **分域**:事实审查 category ∈ {setting,timeline,continuity,character,logic,requirement,leak,evidence,unregistered_thread};编辑审 ∈ {structure,pacing,commercial,motivation}。越界拒绝。
|
|
|
+- **阻断规则**:`critical`→`blocking=true`;`unregistered_thread`(D3)→**强制 `blocking=false`**(即兴伏笔非缺陷,只出候选交作者);其余 severity 由 AI 判 blocking。
|
|
|
+- 复核 `issues_count/blocking_count/has_blocking` 与 `issues` 一致(校验器覆盖写回,继承 v6 review-pipeline 复核纪律)。
|
|
|
+
|
|
|
+### 2.4 落盘
|
|
|
+`工作区/审稿.md` = 草稿 + 两审意见 + 待确认新专名 + 章摘要(spec §8 第7步);`工作区/评审报告/{事实审查,编辑审}.json` 原始输出。模式声明写在审稿单头部(降级:"本次兼容模式,审稿隔离度低于完整两审")。
|
|
|
+
|
|
|
+## 3. AI 态 DTO 与落盘(R2)
|
|
|
+
|
|
|
+- `src/dto/`:`CharacterContext`(角色快照,境界/状态/位置/持有,无路径)——`ReviewInput` 与备料复用。`ChapterBrief` 不另造:M2 `工作区/本章写作材料.md` 即 chapter brief(无新消费者,避免冗余 DTO)。
|
|
|
+- `src/state-machine/persist.js`:AI 产物回流落盘,与 `dto.js`(读侧组装)对称:
|
|
|
+ - 序0 修复确认 → 写回修复后的源文件(经 parser 校验)
|
|
|
+ - 序1 建书 → `book.yaml` + `大纲/总纲.md` + 第一卷卷纲(经 Writer)
|
|
|
+ - 序4 卷复盘 → 卷摘要 + 下卷卷纲 + 勾选的伏笔条目
|
|
|
+ - 序6 细纲 → `工作区/细纲.md`
|
|
|
+- 落盘**只经 M2 Writer 小端口**;AI 提交结构化 DTO,M4 落盘,AI 全程不碰文件路径。
|
|
|
+
|
|
|
+## 4. SessionStart 与书单自愈(R3)
|
|
|
+
|
|
|
+- `readBooksRegistry(workdir)`:读 `.webnovel/books.jsonl`(每行一本:书名/目录/是否当前/最后打开);JSON 行损坏跳过并标记。
|
|
|
+- `scanRebuildBooks(workdir)`:缺失/全损 → 扫描含 `book.yaml` 子目录重建(spec §0 可重建);"当前在写"标记缺失时返回 needsAuthorPick。
|
|
|
+- `assembleSessionContext(workdir)`:产"当前在写哪本/共几本/全书近况入口"注入文本。
|
|
|
+- **无 hook 等价**:状态机入口启动调同一函数 → 与 Claude Code SessionStart hook 注入文本逐字一致(测试断言等价)。
|
|
|
+- **写侧不做**:books.jsonl 写入/换书对话属 M5;M4 只读 + 重建。
|
|
|
+
|
|
|
+## 5. 宿主壳生成器 + drift check(R4)
|
|
|
+
|
|
|
+### 5.1 生成器(src/host-shells/generate.js)
|
|
|
+- 读 `roles/`、`skills/`、`adapters/registry.json` → `dist/<host>/`(agent 壳按平台:Claude Code md+frontmatter / Codex TOML / Gemini md;编译后 SKILL.md)。
|
|
|
+- **平台条件块**(§5.9):零依赖手写最小渲染器——`{{#if agentCapable}}…{{/if}}`、`{{#if hasHooks}}…{{/if}}`、变量插值(命令引用语法/路径)。布尔集只留 `agentCapable`/`hasHooks`(不维护大能力矩阵)。
|
|
|
+- **降级编译进生成物**:无 subagent 平台,生成的 SKILL.md 正文就是顺序执行版 + 兼容声明(不靠运行时判断)。
|
|
|
+- 生成物 `dist/` 不提交(§6.2)。
|
|
|
+
|
|
|
+### 5.2 drift check = 确定性(spec v3.4 §6.2)
|
|
|
+`build-host-shells --check`:同输入连跑两次,断言**逐字节一致**(determinism)+ 生成物过 validator。CI 必跑。(dist 不提交,故非"对比已提交生成物",而是确定性验证。)
|
|
|
+
|
|
|
+### 5.3 package validator
|
|
|
+校验:registry schema、逐宿主 `support.md` 存在、`description` ≤ Codex 8k 预算、生成物**无本机绝对路径**、roles frontmatter 完整。
|
|
|
+
|
|
|
+### 5.4 角色单源:重构而非拷贝 v6
|
|
|
+`roles/事实审查.md`、`roles/编辑审.md` 任务书:
|
|
|
+- **吃 `ReviewInput` DTO**,声明输出 §8 schema;**不含** `python`/脚本调用/文件路径读取(对照 AC6 grep)。
|
|
|
+- 事实审查维度 = v6 五维(setting/timeline/continuity/character/logic)+ v7 新增(requirement 要写到的事核对 / leak 泄密候选判断 / evidence 履历证据验证 / unregistered_thread D3)。
|
|
|
+- 编辑审 = structure/pacing/commercial/motivation;明确排除"自由评文笔好坏"。
|
|
|
+
|
|
|
+## 6. 知识层平移(R5,逐文件审查 + 单一真源)
|
|
|
+
|
|
|
+- 范围严守 spec §11 平移表:**题材模板 / 追读力分类 / 爽点与节奏知识库**,其余 v6 references 不迁。
|
|
|
+- **先选真源,后迁移(用户指令:题材以 CSV 最新版为准,不维护双表)**。v6 同一知识体有新旧两层(新 CSV `references/csv/`+`taxonomy/` vs 老 markdown `skills/*/references/`+`references/genre-profiles.md`),重叠即"两张表"——v7 每体只留一份:
|
|
|
+
|
|
|
+ | 知识体 | v7 唯一真源(取) | v6 弃/折叠 |
|
|
|
+ |---|---|---|
|
|
|
+ | 题材模板 | `taxonomy/genre-index.csv` + `csv/题材与调性推理.csv` | `genre-profiles.md`、`skills/.../genre-tropes.md`、`anti-trope-*.md`(独有内容折叠进 CSV,否则丢) |
|
|
|
+ | 爽点与节奏 | `csv/爽点与节奏.csv` | `genre-hook-payoff-library.md`、`pacing-control.md` 重复部分 |
|
|
|
+ | 追读力分类 | `references/reading-power-taxonomy.md` | (唯一源,无双表) |
|
|
|
+
|
|
|
+- 流程:**P4.1 产真源选定表** → 逐份真源清 v6 问题 → 入 `v7/references/<分类>/` → `迁移报告.md` 记"选谁/弃谁/为什么 + 逐文件改了什么"。
|
|
|
+- **v6 问题清单(grep 把关,AC7)**:
|
|
|
+ | 类别 | 命中样例 | 处置 |
|
|
|
+ |---|---|---|
|
|
|
+ | 双表 | 题材同时存在 CSV 与 markdown 表 | **只留 CSV**,markdown 独有内容折叠进 CSV |
|
|
|
+ | 旧路径 | `设定集/`、`正文/`(非"定稿/正文")、`.webnovel/state.json` | 改 v7 路径或删 |
|
|
|
+ | 退场术语 | "卡"(卡点义)、"棘轮" | 换 spec 术语 |
|
|
|
+ | v6 机制 | `state.json`、doctor、dashboard、v6 skill 名(webnovel-write/plan…)、`python webnovel.py`;CSV 的 `适用技能`/`大模型指令` 列、跨 CSV `推荐检索表` 列 | 删/重写为 v7 中性 |
|
|
|
+ | 反模式 | "评文笔好坏""打分" | 删(两审职责排除) |
|
|
|
+- craft 内容(钩子/兑现/节奏/题材原型/调性/毒点)架构无关,保留。CSV 保持 CSV 形态(机器友好、即单源),不另起 markdown 表复刻。
|
|
|
+- `genre-index.csv` 的 `template_file` 列引用 `templates/genres/*.md`:迁移时一并核对引用完整性(引用的模板要么迁入要么清列),不留悬空引用。
|
|
|
+
|
|
|
+## 7. 取舍
|
|
|
+
|
|
|
+- **DI 注入 reviewers**:把 AI 隔在确定性层外,P0-P5 主体全可 TDD/CI 绿;真模型只在推迟的 smoke 接线。代价:多一层注入接口——值,换来零真 AI 的可测性。
|
|
|
+- **drift = 确定性**(非比对已提交物):符合 v3.4"dist 不提交";代价:不防"手改已分发壳",但分发由 M5 安装器哈希追踪兜底。
|
|
|
+- **角色重构而非拷贝**:这是"不带 v6 问题进 v7"的核心落点;代价:多写,不能 copy——必须,v6 reviewer 直调 runtime 违反铁律。
|
|
|
+- **资产放 v7/ 下**(非仓库根):包自包含,安装器(M5)从 v7/ 取源分发。
|
|
|
+
|
|
|
+## 8. 回滚点
|
|
|
+
|
|
|
+- 各 P 独立、全为**新增目录/文件**(`roles/`、`skills/`、`references/`、`adapters/`、`scripts/`、`src/{review,dto,session,host-shells}`);对 M1-M3 唯一改动是 `state-machine/persist.js` 新增(不改 dto.js 读侧)。
|
|
|
+- 未提交前 `git restore v7/<子目录>` 即回滚;知识迁移是纯新增,删 `references/` 即净。
|