Просмотр исходного кода

docs(v7): M5 spec 回填与任务工件收尾

- 目录结构规范 §4 填实:M5 布局/命令分级协议(scope/allowNoBook)/.webnovel vendored 布局/知识库归属(4.3 填实)
- 质量规范:CI 最低集合补 安装链路 e2e 与主循环全程 CLI;§6.6 宿主通道 JSON 走文件不走 stdin
- 任务 prd/implement 勾选与执行偏差记录(建书 init commit/workspaceFiles 归一/gitignore 收窄/references 白名单决策)
lingfengQAQ 7 часов назад
Родитель
Сommit
1a3bf4981b

+ 17 - 7
.trellis/spec/backend/directory-structure.md

@@ -37,24 +37,30 @@ webnovel-writer/                # 仓库根
 
 3.4 文件排序必须依赖零填充数字前缀(`0152-`、`第05卷`、`伏笔-031`),禁止依赖中文字典序。
 
-## 4. v7 包内布局(M0 落地)
+## 4. v7 包内布局(M0 骨架落地,M5 填实
 
-源码根 `v7/`,ESM、运行时依赖:
+源码根 `v7/`,ESM、运行时依赖仅 js-yaml
 
 ```
 v7/
-├── package.json            # name=webnovel-writer, type=module, engines.node>=22.13.0, 零 deps
+├── package.json            # name=webnovel-writer, type=module, engines.node>=22.13.0
+│                           # files 白名单:bin/ src/ roles/ skills/ adapters/ templates/(npm 包=安装源)
 ├── bin/
-│   └── webnovel-writer.js  # CLI 入口:版本门槛先行 + 子命令分发(init/update 占位)
+│   └── webnovel-writer.js  # CLI 入口:版本门槛先行 + 工作目录定位 + 子命令分发
 ├── src/
-│   ├── runtime/            # 版本门槛等运行时基础
-│   ├── installer/          # 安装器(M5)
+│   ├── runtime/            # 版本门槛、工作目录定位(locate.js,M5)
+│   ├── installer/          # 安装器:detect/vendor/manifest/shells/编排(M5)
+│   ├── session/            # books.jsonl 读写与 SessionStart 注入(M4 读侧/M5 写侧)
+│   ├── commands/           # CLI 薄壳,一命令一文件,全部委托用例层
 │   ├── state-machine/      # 状态机单入口(M3)
+│   ├── review/             # 两审编排与 schema(M4)
+│   ├── host-shells/        # 壳生成器 + validator/drift(M4)
 │   ├── mechanical-check/   # 机检(M2)
 │   ├── prep/               # 备料(M2)
 │   ├── finalize/           # 定稿原子提交(M2)
 │   ├── cache/              # .cache/index.db,node:sqlite(M1,见 O4 缓存设计文档)
 │   └── storage/            # 存储适配器小端口(M1,spec §1.5)
+├── roles/ skills/ adapters/ templates/   # 壳与安装真源(多宿主 spec §6.2)
 └── test/                   # node:test,*.test.js 与 src 镜像
 ```
 
@@ -62,4 +68,8 @@ v7/
 
 4.2 模块为按职责(Use Case)划分,**非通用工具层**;端口拆小,禁止上帝对象(spec §1.5)。
 
-4.3 待补:题材模板与知识库在包内的存放位置(知识层平移任务时定)。
+4.3 知识库真源存放于 `v7/references/`(M4 平移);7.0 运行时尚未接线,**不进 npm files 白名单**——接线里程碑必须同步把它加入白名单并补安装链路断言。
+
+4.4 命令分级协议(M5):命令模块可选导出 `scope`——`'book'`(缺省,得 `{repoPath, cache}`)/ `'workdir'`(得 `{workdir, packageRoot}`,不建缓存)/ `'workdir-or-book'` / `'anywhere'`;空工作目录仍可跑的命令导出 `allowNoBook = true`(当前仅 `next`,状态机以 `repoPath=null` 判序 1 建书)。定位三分支见 `src/runtime/locate.js`:cwd 含 `book.yaml` 直启 → cwd 含 `.webnovel/` 按当前书解析 → 否则人话提示。
+
+4.5 工作目录 `.webnovel/` 为 vendored 运行时(自包含离线可跑):`bin/ src/ roles/ package.json + node_modules/<运行时依赖及传递依赖> + manifest.json(哈希清单)+ books.jsonl(用户数据,安装器只保底不覆盖)`。哈希清单键一律正斜杠(跨平台可移植)。

+ 5 - 1
.trellis/spec/backend/quality-guidelines.md

@@ -37,7 +37,9 @@
 - 删光 `.cache/` 全量重建,查询结果不变;
 - Windows 中文路径全链路;
 - 定稿原子性(中途失败时工作区原样保留);
-- 防呆方言(系统写出的 YAML 平铺/块列表/危险值引号)。
+- 防呆方言(系统写出的 YAML 平铺/块列表/危险值引号);
+- 安装链路端到端(M5,双平台 install-e2e):npm pack 产物装进干净中文路径目录 → init → vendored bin 建书 → next → update 幂等;
+- 主循环全程 CLI(M5):建书→细纲→备料→机检→两审→定稿→next 报下一章,子进程 spawn bin,不走进程内调用。
 
 4.2 修 bug 必须附回归测试;同一问题第二次出现视为流程缺陷,必须复盘。
 
@@ -60,3 +62,5 @@
 6.4 commit message 前缀沿用现状:`feat` / `fix` / `docs` / `chore`(本仓库开发用)。发布产物(marketplace/CHANGELOG)版本走 `docs/operations/plugin-release.md` 流程。
 
 6.5 版本号:`v7/package.json` 在 M5 发版前为预发版号(`7.0.0-alpha`);发版时升 `7.0.0` 并与 README 徽章、`.claude-plugin/marketplace.json`、`plugin.json`、`CHANGELOG.md` 一致——README 版本表是 `plugin-version.yml` CI 硬约束,发版必须同步。
+
+6.6 宿主通道 I/O(M5):AI 产物回流命令的 JSON 输入一律走 `--file`/`--payload` 文件路径,禁止 stdin(Windows 中文管道编码不可靠);小体量 DTO 输出走 stdout(`next --json`),含正文全文的大 JSON 落工作区文件(`review-input`)。相对路径相对书仓库根(无书时相对工作目录)解析。

+ 35 - 26
.trellis/tasks/07-03-m5-installer/implement.md

@@ -4,51 +4,51 @@
 
 ## 0. 前置
 
-- [ ] `task.py start`(用户确认后);分支即 v7(沿 M1-M4 惯例,不另开)
+- [x] `task.py start`(用户确认后);分支即 v7(沿 M1-M4 惯例,不另开)
 
 ## 1. 基座:工作目录定位 + books.jsonl 写侧(PRD B1/B2)
 
-- [ ] 1.1 `src/session/index.js` 扩写侧:`registerBook(workdir, {书名,目录})`(置当前、去重、补最后打开)、`setCurrentBook(workdir, 书名)`、`touchLastOpened(workdir, 目录)`;行格式测试与 M4 读侧同文件
-- [ ] 1.2 `bin/webnovel-writer.js` 命令分级:命令模块可选 `export const scope`;workdir 级不建 CacheManager;书级三分支定位(book.yaml 直启 / .webnovel+当前书 / 人话提示)——design §1.1
-- [ ] 1.3 新命令 `list-books` / `switch-book <书名>` / `session-context`(scope=workdir)
-- [ ] 1.4 测试:定位三分支、换书后书级命令作用于新书、session-context 与 M4 assembleSessionContext 输出逐字一致、损坏 books.jsonl 自愈路径经 CLI 仍成立
+- [x] 1.1 `src/session/index.js` 扩写侧:`registerBook(workdir, {书名,目录})`(置当前、去重、补最后打开)、`setCurrentBook(workdir, 书名)`、`touchLastOpened(workdir, 目录)`;行格式测试与 M4 读侧同文件
+- [x] 1.2 `bin/webnovel-writer.js` 命令分级:命令模块可选 `export const scope`;workdir 级不建 CacheManager;书级三分支定位(book.yaml 直启 / .webnovel+当前书 / 人话提示)——design §1.1
+- [x] 1.3 新命令 `list-books` / `switch-book <书名>` / `session-context`(scope=workdir)
+- [x] 1.4 测试:定位三分支、换书后书级命令作用于新书、session-context 与 M4 assembleSessionContext 输出逐字一致、损坏 books.jsonl 自愈路径经 CLI 仍成立
 
 ## 2. F1 CLI 缝(PRD C,不依赖安装器)
 
-- [ ] 2.1 `next --json`:完整 DTO 上 stdout;缺省人读不变(改 `src/commands/next.js`)
-- [ ] 2.2 `persist-outline` / `persist-volume-review` / `persist-repair`:`--file=` 读 JSON → 委托既有用例;persist-repair 内算 allowedFiles(detectParseFailures)
-- [ ] 2.3 `persist-book`:scope=workdir-or-book;目录判定(design §3.4);`persistCreateBook` 扩指路 AGENTS.md(`templates/` 加书仓库模板);工作目录模式落盘后 registerBook 置当前
-- [ ] 2.4 `src/review/index.js` 抽 `saveReviews`(校验+合并+落盘),`runReviews` 改调它;新命令 `review-input <章号> [--draft=]`(落 `工作区/审稿输入.json`)与 `save-review <章号> --file=`
-- [ ] 2.5 `finalize <章号> --payload=`:读 JSON → `finalizeChapter` → 报 commit 短哈希与下一步
-- [ ] 2.6 逐命令测试:正常路径 + 文件缺失/JSON 坏/schema 不过的人话报错与退出码;`--file` 中文内容往返
-- [ ] 2.7 集成测试(D2 出口):`test/integration/` 子进程 spawn bin 跑通 建书→细纲→草稿→机检→review-input→save-review(桩JSON)→finalize→`next --json` 报第 2 章——主循环全程 CLI
+- [x] 2.1 `next --json`:完整 DTO 上 stdout;缺省人读不变(改 `src/commands/next.js`)
+- [x] 2.2 `persist-outline` / `persist-volume-review` / `persist-repair`:`--file=` 读 JSON → 委托既有用例;persist-repair 内算 allowedFiles(detectParseFailures)
+- [x] 2.3 `persist-book`:scope=workdir-or-book;目录判定(design §3.4);`persistCreateBook` 扩指路 AGENTS.md(`templates/` 加书仓库模板);工作目录模式落盘后 registerBook 置当前
+- [x] 2.4 `src/review/index.js` 抽 `saveReviews`(校验+合并+落盘),`runReviews` 改调它;新命令 `review-input <章号> [--draft=]`(落 `工作区/审稿输入.json`)与 `save-review <章号> --file=`
+- [x] 2.5 `finalize <章号> --payload=`:读 JSON → `finalizeChapter` → 报 commit 短哈希与下一步
+- [x] 2.6 逐命令测试:正常路径 + 文件缺失/JSON 坏/schema 不过的人话报错与退出码;`--file` 中文内容往返
+- [x] 2.7 集成测试(D2 出口):`test/integration/` 子进程 spawn bin 跑通 建书→细纲→草稿→机检→review-input→save-review(桩JSON)→finalize→`next --json` 报第 2 章——主循环全程 CLI
 
 ## 3. 安装器(PRD A)
 
-- [ ] 3.1 `adapters/registry.json` 每宿主加 `detect_bin` / `install_dir`;`src/host-shells/validator.js` 同步校验;跑 drift check 确认不破
-- [ ] 3.2 `src/installer/detect.js`:PATH 探测(注入 env 可测,win32 PATHEXT);`--hosts` 覆盖解析
-- [ ] 3.3 `src/installer/vendor.js`:包根定位 + `.webnovel/` 复制清单(bin/src/roles/package.json + js-yaml 目录,design §1.2);books.jsonl 只建不覆盖
-- [ ] 3.4 `src/installer/manifest.js`:sha256 清单读写 + update 三态判定(AGENTS.md 记块内哈希)
-- [ ] 3.5 `src/installer/shells.js`:generateHostShells 产物平移进 `install_dir`;claude-code settings.json SessionStart 幂等合并(不进清单)
-- [ ] 3.6 `src/installer/index.js` 编排 init(检测→布局→壳→AGENTS.md→manifest→报告)与 update(哈希三态 + `--force` + AGENTS.md 块内更新 + settings 幂等合并 + vendored 内自更新提示);`src/commands/init.js` / `update.js` 薄壳
-- [ ] 3.7 测试:init 布局逐项断言(AC2)、重复 init=update 语义、update 三态(AC3)、未检测到宿主→公约数层 + 指引、`.webnovel/` 里的 bin 可 `node` 直跑(spawn 验证 vendored 自包含)
+- [x] 3.1 `adapters/registry.json` 每宿主加 `detect_bin` / `install_dir`;`src/host-shells/validator.js` 同步校验;跑 drift check 确认不破
+- [x] 3.2 `src/installer/detect.js`:PATH 探测(注入 env 可测,win32 PATHEXT);`--hosts` 覆盖解析
+- [x] 3.3 `src/installer/vendor.js`:包根定位 + `.webnovel/` 复制清单(bin/src/roles/package.json + js-yaml 目录,design §1.2);books.jsonl 只建不覆盖
+- [x] 3.4 `src/installer/manifest.js`:sha256 清单读写 + update 三态判定(AGENTS.md 记块内哈希)
+- [x] 3.5 `src/installer/shells.js`:generateHostShells 产物平移进 `install_dir`;claude-code settings.json SessionStart 幂等合并(不进清单)
+- [x] 3.6 `src/installer/index.js` 编排 init(检测→布局→壳→AGENTS.md→manifest→报告)与 update(哈希三态 + `--force` + AGENTS.md 块内更新 + settings 幂等合并 + vendored 内自更新提示);`src/commands/init.js` / `update.js` 薄壳
+- [x] 3.7 测试:init 布局逐项断言(AC2)、重复 init=update 语义、update 三态(AC3)、未检测到宿主→公约数层 + 指引、`.webnovel/` 里的 bin 可 `node` 直跑(spawn 验证 vendored 自包含)
 
 ## 4. 壳接线(PRD A4/B4)
 
-- [ ] 4.1 生成器上下文加 `cmd`;SKILL.md 全部命令引用改 `{{cmd}}`;写章流程接 F1 通道(`review-input`→两审→`save-review`→`finalize`,「继续」= `next --json`)
-- [ ] 4.2 `node scripts/build-host-shells.mjs --check` 绿;host-shells 既有测试更新(文案级断言按需改——测试是探针不是约束)
+- [x] 4.1 生成器上下文加 `cmd`;SKILL.md 全部命令引用改 `{{cmd}}`;写章流程接 F1 通道(`review-input`→两审→`save-review`→`finalize`,「继续」= `next --json`)
+- [x] 4.2 `node scripts/build-host-shells.mjs --check` 绿;host-shells 既有测试更新(文案级断言按需改——测试是探针不是约束)
 
 ## 5. 发布产物与 CI(PRD D)
 
-- [ ] 5.1 `package.json` 加 `files` 白名单(bin/src/roles/skills/adapters/templates);`npm pack --dry-run` 核对清单
-- [ ] 5.2 CI(v7-ci.yml)加安装链路 job:npm pack → 干净**中文路径**临时目录 npm install 产物 → init → persist-book 建第一本书 → 布局断言 → `next --json`;ubuntu + windows 双平台(AC1 CI 半)
-- [ ] 5.3 本地全量:`node --test` 绿 + drift check 绿 + pack e2e 本地演练
+- [x] 5.1 `package.json` 加 `files` 白名单(bin/src/roles/skills/adapters/templates);`npm pack --dry-run` 核对清单
+- [x] 5.2 CI(v7-ci.yml)加安装链路 job:npm pack → 干净**中文路径**临时目录 npm install 产物 → init → persist-book 建第一本书 → 布局断言 → `next --json`;ubuntu + windows 双平台(AC1 CI 半)
+- [x] 5.3 本地全量:`node --test` 绿 + drift check 绿 + pack e2e 本地演练
 
 ## 6. 收尾
 
-- [ ] 6.1 `--help` 增新命令段;bin 帮助文案与实际命令清单一致性测试(如已有惯例则从之)
+- [x] 6.1 `--help` 增新命令段;bin 帮助文案与实际命令清单一致性测试(如已有惯例则从之)
 - [ ] 6.2 手测(AC1 手测半,用户执行):Windows 中文用户名真机 npx(pack 产物)init → 建书 → 写一章走到定稿;记录进任务 notes
-- [ ] 6.3 spec 更新(3.3):实施计划 M5 打勾与偏差记录;registry/support.md 如有字段变化同步;memory 更新
+- [x] 6.3 spec 更新(3.3):实施计划 M5 打勾与偏差记录;registry/support.md 如有字段变化同步;memory 更新
 - [ ] 6.4 提交(3.4):分批 commit(基座 / F1 / 安装器 / 壳与 CI)
 
 ## V. 验证命令
@@ -68,3 +68,12 @@ node bin/webnovel-writer.js --help         # 人话面
 - `src/review/index.js` 抽函数:对外签名不变,review 既有测试是守门
 - Windows 本地跑 node 测试无需 PYTHONUTF8(那是 pytest 的坑);spawn 子进程一律 args 数组不走 shell
 - 回滚:各步独立 commit,`git revert` 单步可退;安装产物层面 init/update 幂等,重跑即修复
+
+## 执行偏差与决策记录(实施中新增)
+
+1. `persistCreateBook` 补 **init commit(`init: 建书《书名》`)+ git 身份局部兜底**:不提交则建书完 `next` 立刻误触序 2 手改检测(main-loop 旧测试靠手工 commit 掩盖);作者机器可能没配 git 身份,`ensureIdentity` 只设书仓库局部。超出原计划清单,属 D2 出口必需。
+2. `finalize` CLI 归一 `workspaceFiles` 的「工作区/」前缀:用例层约定是工作区内相对名,宿主必然写 repo 相对路径,`rm force` 会静默漏清(CLI e2e 抓到)。
+3. 根 `.gitignore` 的全局 `AGENTS.md` 规则收窄为 `/AGENTS.md`:M4 遗留——`v7/templates/AGENTS.md` 从未入库,干净 checkout 下 init 布局残缺、CI 安装链路必红。
+4. `references/` 知识库不进 npm `files` 白名单:运行时(src/SKILL/roles)均未消费;归属与接线义务记入 backend 目录结构规范 §4.3。
+5. 安装链路 e2e 走 `npm run e2e:install`:用 `npm_execpath` 定位 npm、全程 args 数组不经 shell,规避 Windows 中文路径引号与 .cmd spawn 限制。
+6. 安装器报告的支持等级直引 registry `verified` 原文(「结构就绪,真模型 smoke 推迟 beta」),不夸大为「亲测」。

+ 8 - 8
.trellis/tasks/07-03-m5-installer/prd.md

@@ -56,14 +56,14 @@
 
 ## Acceptance Criteria
 
-- [ ] AC1 干净 Windows 中文用户名环境一条命令装出工作目录并建第一本书:CI 用例绿(npm pack 产物 + 中文路径临时目录全链路)+ 手测一次通过
-- [ ] AC2 `init` 装出的布局逐项存在且内容正确:`AGENTS.md`(标记块)、`.webnovel/`(脚本可 `node` 直跑、`books.jsonl`、哈希清单)、检测到的平台壳;报告输出含支持等级与下一步指引
-- [ ] AC3 `update`:未改文件被更新;手改文件被跳过且列出;`AGENTS.md` 块外内容保留;`--force` 可覆盖
-- [ ] AC4 写章八阶段每一步都有宿主可调 CLI 通道:F1 清单 8 个命令逐个有测试(含 schema 校验失败、文件缺失的人话报错)
-- [ ] AC5 `finalize→next` 端到端经 CLI 子进程跑通,next 报「起草第 N+1 章」不重抄
-- [ ] AC6 工作目录定位三分支(书仓库直启 / 工作目录+当前书 / 无处可依)各有测试;换书后 next 作用于新书
-- [ ] AC7 SessionStart 注入:hook 路径与无 hook 宿主状态机入口路径输出逐字一致(既有测试延伸到 CLI 通道)
-- [ ] AC8 全量测试绿 + CI 双平台绿;drift check 对新增模板变量仍确定性通过
+- [ ] AC1 干净 Windows 中文用户名环境一条命令装出工作目录并建第一本书:CI 用例绿(npm pack 产物 + 中文路径临时目录全链路)+ 手测一次通过 —— CI job 已建(install-e2e,双平台)本地全通过;待推送后 CI 绿 + 用户手测
+- [x] AC2 `init` 装出的布局逐项存在且内容正确:`AGENTS.md`(标记块)、`.webnovel/`(脚本可 `node` 直跑、`books.jsonl`、哈希清单)、检测到的平台壳;报告输出含支持等级与下一步指引
+- [x] AC3 `update`:未改文件被更新;手改文件被跳过且列出;`AGENTS.md` 块外内容保留;`--force` 可覆盖
+- [x] AC4 写章八阶段每一步都有宿主可调 CLI 通道:F1 清单 8 个命令逐个有测试(含 schema 校验失败、文件缺失的人话报错)
+- [x] AC5 `finalize→next` 端到端经 CLI 子进程跑通,next 报「起草第 N+1 章」不重抄
+- [x] AC6 工作目录定位三分支(书仓库直启 / 工作目录+当前书 / 无处可依)各有测试;换书后 next 作用于新书
+- [x] AC7 SessionStart 注入:hook 路径与无 hook 宿主状态机入口路径输出逐字一致(既有测试延伸到 CLI 通道)
+- [ ] AC8 全量测试绿 + CI 双平台绿;drift check 对新增模板变量仍确定性通过 —— 本地 335 绿 + drift 绿;CI 待推送验证
 
 ## Out of Scope