Переглянути джерело

fix: 统一路径格式为卷目录结构,修复硬编码路径问题

- workflow_manager.py: 使用 chapter_paths 模块定位章节文件
- golden_three_checker.py: 添加 --auto 参数自动定位前三章
- 更新 webnovel-resume.md, workflow-resume.md, git-workflow.md 文档示例

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
lingfengQAQ 5 місяців тому
батько
коміт
51a94801c6

+ 15 - 11
.claude/commands/webnovel-resume.md

@@ -83,7 +83,7 @@ python .claude/skills/webnovel-writer/scripts/workflow_manager.py detect
   "elapsed_seconds": 315,
   "artifacts": {
     "chapter_file": {
-      "path": "正文/第0007章.md",
+      "path": "正文/第1卷/第007章.md",
       "exists": true,
       "size_bytes": 1500,
       "status": "incomplete"
@@ -100,9 +100,9 @@ python .claude/skills/webnovel-writer/scripts/workflow_manager.py detect
     "option": "A",
     "label": "删除半成品,从Step 1重新开始",
     "risk": "low",
-    "description": "清理 正文/第0007章.md,重新生成章节",
+    "description": "清理 正文/第1卷/第007章.md,重新生成章节",
     "actions": [
-      "删除 正文/第0007章.md(如存在)",
+      "删除 正文/第1卷/第007章.md(如存在)",
       "清理 Git 暂存区",
       "清理中断状态",
       "执行 /webnovel-write 7"
@@ -185,9 +185,9 @@ python .claude/skills/webnovel-writer/scripts/workflow_manager.py detect
 恢复选项:
 A) 删除半成品,从Step 1重新开始(推荐)⭐
    风险:低
-   清理 正文/第0007章.md,重新生成章节
+   清理 正文/第1卷/第007章.md,重新生成章节
    操作步骤:
-   - 删除 正文/第0007章.md(如存在)
+   - 删除 正文/第1卷/第007章.md(如存在)
    - 清理 Git 暂存区
    - 清理中断状态
    - 执行 /webnovel-write 7
@@ -228,7 +228,7 @@ B) 回滚到Ch6,放弃Ch7所有进度
 python .claude/skills/webnovel-writer/scripts/workflow_manager.py cleanup --chapter {chapter_num}
 
 # 预期输出:
-# ✅ 已清理: 正文/第0007章.md, Git暂存区已清理
+# ✅ 已清理: 正文/第1卷/第007章.md, Git暂存区已清理
 
 # Step 4.2: 清除中断状态
 python .claude/skills/webnovel-writer/scripts/workflow_manager.py clear
@@ -243,7 +243,7 @@ python .claude/skills/webnovel-writer/scripts/workflow_manager.py clear
 
 Step 1: 清理半成品文件
 [运行: python workflow_manager.py cleanup --chapter 7]
-✅ 已清理: 正文/第0007章.md, Git暂存区已清理
+✅ 已清理: 正文/第1卷/第007章.md, Git暂存区已清理
 
 Step 2: 清除中断状态
 [运行: python workflow_manager.py clear]
@@ -481,13 +481,17 @@ Before you tell the user "Recovery complete", **YOU MUST verify**:
 **Fallback Strategy**(仅当workflow_state.json不存在时):
 
 ```bash
-# 启发式检测
+# 启发式检测(兼容卷目录结构)
 current_chapter=$(jq '.progress.current_chapter' .webnovel/state.json)
 next_chapter=$((current_chapter + 1))
-next_file="正文/第$(printf '%04d' $next_chapter)章.md"
+volume_num=$(( (next_chapter - 1) / 50 + 1 ))
+next_file="正文/第${volume_num}卷/第$(printf '%03d' $next_chapter)章.md"
 
-if [ -f "$next_file" ]; then
-  echo "⚠️ 检测到半成品: $next_file"
+# 也检查旧格式
+legacy_file="正文/第$(printf '%04d' $next_chapter)章.md"
+
+if [ -f "$next_file" ] || [ -f "$legacy_file" ]; then
+  echo "⚠️ 检测到半成品: $next_file 或 $legacy_file"
   echo "建议: 删除并重新创作"
 else
   echo "✅ 状态一致,可继续创作Ch$next_chapter"

+ 6 - 6
.claude/skills/webnovel-writer/references/git-workflow.md

@@ -56,7 +56,7 @@ git log
 ```
 
 **执行流程**:
-1. 生成第 45 章内容 → 保存到 `正文/第0045章.md`
+1. 生成第 45 章内容 → 保存到 `正文/第1卷/第045章-外门大比.md`(卷目录结构)
 2. 更新 `state.json`(主角实力/伏笔/关系等)
 3. **自动调用**:
    ```bash
@@ -71,7 +71,7 @@ git tag ch0045
 ```
 
 **结果**:
-- state.json 和 第0045章.md **同时提交**
+- state.json 和章节文件 **同时提交**
 - 创建 tag `ch0045` 便于快速定位
 
 ---
@@ -102,8 +102,8 @@ python scripts/backup_manager.py --rollback 140
 **数据一致性保证**:
 ```
 ✅ state.json: 筑基 7 层
-✅ 正文/第0140章.md: 最后一章(筑基期内容)
-✅ 正文/第0150章.md: 不存在(已回滚)
+✅ 正文/第3卷/第140章.md: 最后一章(筑基期内容)
+✅ 正文/第4卷/第150章.md: 不存在(已回滚)
 ```
 
 ---
@@ -122,8 +122,8 @@ python scripts/backup_manager.py --diff 100 150
 
 📈 文件变更统计:
  .webnovel/state.json     | 25 +++++++++++++
- 正文/第0101章.md         | 120 +++++++++++++++++++++++
- 正文/第0102章.md         | 115 +++++++++++++++++++++++
+ 正文/第3卷/第101章.md    | 120 +++++++++++++++++++++++
+ 正文/第3卷/第102章.md    | 115 +++++++++++++++++++++++
  ...(共 50 个新增章节)
 
 📝 state.json 详细差异:

+ 31 - 22
.claude/skills/webnovel-writer/references/workflow-resume.md

@@ -46,14 +46,14 @@ python .claude/skills/webnovel-writer/scripts/workflow_manager.py detect
   "elapsed_seconds": 315,
   "artifacts": {
     "chapter_file": {
-      "path": "正文/第0007章.md",
+      "path": "正文/第1卷/第007章.md",
       "exists": true,
       "size_bytes": 1500,
       "status": "incomplete"
     },
     "git_status": {
       "uncommitted_changes": true,
-      "unstaged_files": ["正文/第0007章.md"]
+      "unstaged_files": ["正文/第1卷/第007章.md"]
     }
   }
 }
@@ -66,9 +66,9 @@ python .claude/skills/webnovel-writer/scripts/workflow_manager.py detect
     "option": "A",
     "label": "删除半成品,从Step 1重新开始",
     "risk": "low",
-    "description": "清理 正文/第0007章.md,重新生成章节",
+    "description": "清理 正文/第1卷/第007章.md,重新生成章节",
     "actions": [
-      "删除 正文/第0007章.md(如存在)",
+      "删除 正文/第1卷/第007章.md(如存在)",
       "清理 Git 暂存区",
       "清理中断状态",
       "执行 /webnovel-write 7"
@@ -110,7 +110,7 @@ python .claude/skills/webnovel-writer/scripts/workflow_manager.py detect
 
 恢复选项:
 A) 删除半成品,从Step 1重新开始(推荐)⭐
-   - 清理 正文/第0007章.md
+   - 清理 正文/第1卷/第007章.md
    - 清理 Git 暂存区
    - 重新执行完整流程
 
@@ -136,7 +136,7 @@ python workflow_manager.py cleanup --chapter 7
 
 **预期输出**:
 ```
-✅ 已清理: 正文/第0007章.md, Git暂存区已清理
+✅ 已清理: 正文/第1卷/第007章.md, Git暂存区已清理
 ```
 
 2. **清除中断状态**:
@@ -213,7 +213,7 @@ Ch7的所有进度已丢弃
 ```bash
 # Step 1: 清理半成品
 python workflow_manager.py cleanup --chapter 7
-# 输出: ✅ 已清理: 正文/第0007章.md, Git暂存区已清理
+# 输出: ✅ 已清理: 正文/第1卷/第007章.md, Git暂存区已清理
 
 # Step 2: 清除中断状态
 python workflow_manager.py clear
@@ -245,7 +245,7 @@ python workflow_manager.py clear
 **恢复策略**:
 ```bash
 # 重新运行实体提取(幂等操作)
-python extract_entities.py "正文/第{N:04d}章.md" --auto
+python extract_entities.py --project-root "$PROJECT_ROOT" --chapter {N} --auto
 
 # 继续后续步骤
 # 手动执行Step 4-7,或重新执行整个命令
@@ -270,9 +270,9 @@ python extract_entities.py "正文/第{N:04d}章.md" --auto
 cat .webnovel/state.json | jq '.progress.current_chapter'
 # 输出: 6 (应该是7,说明未更新)
 
-# 检查文件是否存在
-ls -lh 正文/第0007章.md
-# 输出: -rw-r--r-- 1 user 3542 Jan 1 14:35 正文/第0007章.md
+# 检查文件是否存在(兼容卷目录)
+ls -lh "正文/第1卷/第007章.md" 2>/dev/null || ls -lh "正文/第0007章.md"
+# 输出示例: -rw-r--r-- 1 user 3542 Jan 1 14:35 正文/第1卷/第007章.md
 ```
 
 **Step 2: 决定恢复方案**:
@@ -291,7 +291,8 @@ python update_state.py \
 **选项B(高风险)**:回滚到Ch6
 ```bash
 git checkout ch0006 -- .webnovel/state.json
-rm 正文/第0007章.md
+# 删除章节文件(兼容新旧目录结构)
+rm -f "正文/第1卷/第007章.md" "正文/第0007章.md"
 python workflow_manager.py clear
 ```
 
@@ -324,7 +325,8 @@ git tag -l | grep ch0007
 ```bash
 git reset HEAD .
 git checkout -- .
-rm 正文/第0007章.md
+# 删除章节文件(兼容新旧目录结构)
+rm -f "正文/第1卷/第007章.md" "正文/第0007章.md"
 python workflow_manager.py clear
 ```
 
@@ -422,8 +424,9 @@ python workflow_manager.py detect
 
 **检测**:
 ```bash
-ls -lh 正文/*.md | tail -5
-# 发现: 第0007章.md (1500字), 第0008章.md (800字)
+# 检测所有章节文件(兼容卷目录结构)
+find 正文 -name "第*.md" -type f 2>/dev/null | xargs ls -lh | tail -5
+# 发现: 第007章.md (1500字), 第008章.md (800字)
 ```
 
 **策略**:
@@ -432,8 +435,12 @@ ls -lh 正文/*.md | tail -5
 cat .webnovel/state.json | jq '.progress.current_chapter'
 # 输出: 6
 
-# 决策: 删除所有半成品
-rm 正文/第0007章.md 正文/第0008章.md
+# 决策: 删除所有半成品(兼容卷目录)
+find 正文 -name "第007章*.md" -delete
+find 正文 -name "第008章*.md" -delete
+# 或使用 workflow_manager.py cleanup
+python workflow_manager.py cleanup --chapter 7
+python workflow_manager.py cleanup --chapter 8
 
 # 从Ch6的稳定状态重新开始
 python workflow_manager.py clear
@@ -453,12 +460,14 @@ python workflow_manager.py clear
 # Step 1: 读取state.json
 current_chapter=$(jq '.progress.current_chapter' .webnovel/state.json)
 
-# Step 2: 检查章节文件
+# Step 2: 检查章节文件(兼容卷目录结构)
 next_chapter=$((current_chapter + 1))
-next_file="正文/第$(printf '%04d' $next_chapter)章.md"
+volume_num=$(( (next_chapter - 1) / 50 + 1 ))
+next_file="正文/第${volume_num}卷/第$(printf '%03d' $next_chapter)章.md"
+legacy_file="正文/第$(printf '%04d' $next_chapter)章.md"
 
-if [ -f "$next_file" ]; then
-  echo "⚠️ 检测到半成品: $next_file"
+if [ -f "$next_file" ] || [ -f "$legacy_file" ]; then
+  echo "⚠️ 检测到半成品: $next_file 或 $legacy_file"
   echo "建议: 删除并重新创作"
 else
   echo "✅ 状态一致,可继续创作Ch$next_chapter"
@@ -546,7 +555,7 @@ AI: ✅ 执行选项A:删除半成品,重新开始
 
     Step 1: 清理半成品文件
     [运行: python workflow_manager.py cleanup --chapter 7]
-    ✅ 已清理: 正文/第0007章.md, Git暂存区已清理
+    ✅ 已清理: 正文/第1卷/第007章.md, Git暂存区已清理
 
     Step 2: 清除中断状态
     [运行: python workflow_manager.py clear]

+ 58 - 8
.claude/skills/webnovel-writer/scripts/golden_three_checker.py

@@ -12,17 +12,24 @@ Golden Three Chapters Checker
 
 使用方法:
 python golden_three_checker.py <章节文件路径1> <章节文件路径2> <章节文件路径3>
+python golden_three_checker.py --auto  # 自动定位前三章(推荐)
 
 示例:
-python .claude/skills/webnovel-writer/scripts/golden_three_checker.py "正文/第0001章.md" "正文/第0002章.md" "正文/第0003章.md"
+python golden_three_checker.py "正文/第1卷/第001章.md" "正文/第1卷/第002章.md" "正文/第1卷/第003章.md"
+python golden_three_checker.py --project-root "webnovel-project" --auto
 """
 
 import sys
 import os
 import re
 import json
+import argparse
 from pathlib import Path
 
+# 导入项目定位和章节路径模块
+from project_locator import resolve_project_root
+from chapter_paths import find_chapter_file
+
 # Windows UTF-8 输出修复
 if sys.platform == 'win32':
     import io
@@ -333,13 +340,56 @@ class GoldenThreeChecker:
 
 
 def main():
-    if len(sys.argv) < 4:
-        print("用法: python golden_three_checker.py <第1章路径> <第2章路径> <第3章路径>")
-        print("\n示例:")
-        print('python .claude/skills/webnovel-writer/scripts/golden_three_checker.py "正文/第0001章.md" "正文/第0002章.md" "正文/第0003章.md"')
-        sys.exit(1)
-
-    chapter_files = sys.argv[1:4]
+    parser = argparse.ArgumentParser(
+        description="黄金三章检查工具",
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        epilog="""
+示例:
+  # 指定文件路径(兼容旧格式)
+  python golden_three_checker.py "正文/第0001章.md" "正文/第0002章.md" "正文/第0003章.md"
+
+  # 自动定位前三章(推荐)
+  python golden_three_checker.py --auto
+
+  # 指定项目根目录 + 自动定位
+  python golden_three_checker.py --project-root "webnovel-project" --auto
+""".strip(),
+    )
+
+    parser.add_argument("chapter_files", nargs="*", help="前三章文件路径(可选,使用 --auto 时自动定位)")
+    parser.add_argument("--auto", action="store_true", help="自动定位前三章文件")
+    parser.add_argument("--project-root", default=None, help="项目根目录(包含 .webnovel/state.json)")
+
+    args = parser.parse_args()
+
+    chapter_files = []
+
+    if args.auto or not args.chapter_files:
+        # 自动定位前三章
+        try:
+            project_root = resolve_project_root(args.project_root)
+        except FileNotFoundError as e:
+            print(f"❌ {e}")
+            sys.exit(1)
+
+        for i in range(1, 4):
+            chapter_path = find_chapter_file(project_root, i)
+            if chapter_path:
+                chapter_files.append(str(chapter_path))
+            else:
+                print(f"❌ 找不到第 {i} 章文件")
+                sys.exit(1)
+
+        print(f"📂 项目根目录: {project_root}")
+        print(f"📄 检测到前三章: {', '.join(Path(f).name for f in chapter_files)}\n")
+    else:
+        if len(args.chapter_files) < 3:
+            print("用法: python golden_three_checker.py <第1章路径> <第2章路径> <第3章路径>")
+            print("  或: python golden_three_checker.py --auto")
+            print("\n示例:")
+            print('python golden_three_checker.py "正文/第1卷/第001章.md" "正文/第1卷/第002章.md" "正文/第1卷/第003章.md"')
+            sys.exit(1)
+        chapter_files = args.chapter_files[:3]
 
     try:
         checker = GoldenThreeChecker(chapter_files)

+ 11 - 2
.claude/skills/webnovel-writer/scripts/workflow_manager.py

@@ -200,7 +200,16 @@ def analyze_recovery_options(interrupt_info):
     elif step_id == 'Step 2':
         # Step 2中断:可能有半成品文件
         chapter_file = interrupt_info['artifacts'].get('chapter_file', {})
-        chapter_path = f"正文/第{chapter_num:04d}章.md"
+
+        # 使用 chapter_paths 模块定位章节文件(兼容新旧目录结构)
+        project_root = find_project_root()
+        existing_chapter = find_chapter_file(project_root, chapter_num)
+        if existing_chapter:
+            chapter_path = str(existing_chapter.relative_to(project_root))
+        else:
+            # 如果不存在,使用新格式的默认路径
+            draft_path = default_chapter_draft_path(project_root, chapter_num)
+            chapter_path = str(draft_path.relative_to(project_root))
 
         options = [{
             'option': 'A',
@@ -216,7 +225,7 @@ def analyze_recovery_options(interrupt_info):
         }]
 
         # 检查文件是否存在
-        if os.path.exists(chapter_path):
+        if existing_chapter and existing_chapter.exists():
             options.append({
                 'option': 'B',
                 'label': '回滚到上一章',