Skill: jinqiu193/long-doc-agent (version 1.0.0)

--- name: long-doc-agent license: MIT metadata: version: "3.3.0" category: document-generation triggers: - "write feasibility report" - "write proposal" - "multi-chapter" - "parallel writing" - "agent write document" description: > Multi-Agent collaborative system for writing ultra-long feasibility study reports. Phase 0 Requirements → Phase 1 Planner Outline → Phase 2 Parallel Sub-Agent Writing → Phase 2.5 Cross-Chapter Consistency Review → Phase 3 Integrator Final Output (styled docx). Core files: integrate_report.py (integration/CLI), parallel_tracker.py (parallel progress tracking). --- # Ultra-Long Feasibility Report Multi-Agent Collaborative Writing v3.3 ## Changelog (v3.3) - ✅ Table parsing fully fixed (`_flush_table` not calling `_parse_md_table` caused character-by-character splitting) - ✅ Colorful chapter headings officially launched (H1 deep navy full-row band / H2 medium blue block / H3 light blue left bar) - ✅ Styled tables launched (deep blue header + white text + alternating row colors) - ✅ Key callout boxes launched (【关键】【注意】【优势】【风险】【数据】 color-coded cards) - ✅ Cover style enhanced (tech-digital style deep ocean blue full-screen background + white text) - ✅ Cover/Contents/Executive Summary title bars all colored - ✅ Fixed `cover_style` integer vs string comparison preventing cover from applying - ✅ Fixed `RGBColor.from_string()` instead of `eval` to avoid type errors ## Core Capabilities - **Multi-Agent Parallel**: Up to 5 sub-agents writing concurrently, doubled efficiency - **Incremental Updates**: Chapters with unchanged content are skipped, faster processing - **Beautiful Formatting**: Auto-generated cover, table-style TOC, colorful chapter headings, key callout boxes, styled tables - **Feishu RAG**: Auto-search Feishu knowledge base to supplement reference materials - **6 Cover Styles**: Switch freely to suit different scenarios --- ## File Structure ``` skill_dir/ ├── SKILL.md # This file ├── integrate_report.py # Core engine: parse/ integrate/CLI ├── parallel_tracker.py # Parallel progress tracking └── references/ # Sub-process reference documents ├── phase0_guide.md # Phase 0 requirements confirmation flow ├── phase1_guide.md # Planner prompt template ├── phase2_guide.md # Sub-Agent prompt template ├── table_format_guide.md # Markdown table format specification └── bug_fix_guide.md # Bug troubleshooting & forced rebuild ``` > **First-time setup**: Ensure the `F:/agent/chapters/` directory exists. --- ## Pipeline Routing ``` User Task ├─ First writing request ("I want to write xxx"/"help me write a feasibility report") │ → Phase 0 Requirements → Phase 1 Planner │ ├─ Outline exists, request to start writing │ → Phase 2 Parallel Sub-Agents │ ├─ A chapter needs modification │ → Small change: directly edit F:/agent/chapters/0X-xxx.txt │ → Large change: regenerate that chapter │ ├─ All chapters done, request docx generation │ → Phase 2.5 Review → Phase 3 Integrator │ ├─ Independent small proposal (2~5 chapters, no existing chapters dependency) │ → Write Markdown directly → make_docx.py to generate styled docx │ → See: references/bug_fix_guide.md "make_docx.py Mode" │ └─ Just need to check progress/glossary/reference materials → Direct CLI commands ``` --- ## Phase 0: Requirements Confirmation Confirm 4 items in order; all confirmed → Phase 1: 1. **Writing Topic**: document type / audience / style / special constraints 2. **Background Information**: project background / construction goals / industry context 3. **Reference Materials** (most important): - A. Local file path or paste directly - B. Feishu document (RAG search) - C. Paste content directly - D. Not provided for now 4. **Outline Confirmation**: After planner outputs outline, user chooses A.Start / B.Adjust / C.Cancel > More reference materials → more business-aligned content. See `references/phase0_guide.md` for details. --- ## Phase 1: Planner **Input**: Phase 0 topic / background / reference materials **Execute**: ```bash python integrate_report.py glossary ``` Auto-generates `plan.json` + `plan_outline_snapshot.md` > Full prompt template in `references/phase1_guide.md` **After completion, send WeChat notification** (using `message` tool, channel=`openclaw-weixin`): ``` 📋 Report Outline Generated 📌 《[Report Topic]》 📊 Chapters: [X] chapters 🔍 Industry: [Industry Field] ✅ Reply "start writing" once the outline is confirmed — the system will launch parallel creation! ``` --- ## Phase 2: Parallel Sub-Agents **Execution flow** (fully automatic, no manual confirmation): 1. Display outline / current batch status (display only, no waiting) 2. `python parallel_tracker.py clear` to clear previous batch state 3. Start up to 5 concurrent sub-agents (`sessions_spawn`), automatically execute all batches 4. `python parallel_tracker.py wait` to monitor in background until this batch is complete 5. After completion, automatically run `python integrate_report.py convert-batch` **Sub-Agent prompt template**: see `references/phase2_guide.md` **After each batch completes, send WeChat notification** (using `message` tool, channel=`openclaw-weixin`): ``` ✅ Batch [X] Chapter Writing Complete! 📖 Completed: [Done]/[Total] chapters 📝 This batch: • [Chapter 1 Title] • [Chapter 2 Title] • [Chapter 3 Title] (if any) ⏳ Next batch: [Next batch chapter list] (Automatically proceeds to next batch, no manual confirmation needed) ``` - Small change: directly edit `F:/agent/chapters/0X-xxx.txt`, save and regenerate - Large change: re-trigger sub-agent to rewrite, replacing the original file --- ## Phase 2.5: Cross-Chapter Consistency Review ```bash python integrate_report.py check ``` Review numerical indicator consistency and terminology uniformity (对照 glossary.json) **After review completes, send WeChat notification** (using `message` tool, channel=`openclaw-weixin`): ``` 🔍 Consistency Review Complete ✅ Terminology uniformity: OK ✅ Numerical indicators: consistent ✅ Cross-chapter references: no conflicts 📄 Proceeding to final integration phase... ``` --- ## Phase 3: Integrator Summary ```bash python integrate_report.py ``` Auto-completes: parse chapters (error isolation) → update glossary → consistency review → generate styled docx **After final completion, send WeChat notification** (using `message` tool, channel=`openclaw-weixin`): ``` 🎉🎉🎉 Report Writing Complete! 🎉🎉🎉 📄 《[Report Topic]》 📊 Scale: [X] chapters / ~[Y] thousand characters 🎨 Cover Style: [Style Name] ✅ Styled report generated! 📁 File location: F:/agent/chapters/output/ Wenxin, full text ready for your review~ ``` --- ## Document Beautification Features (Auto-Applied) Generated reports automatically include the following formatting effects (selected via `cover_style` field in `plan.json`): 1. **6 Cover Styles** — Edit `plan.json` → `cover_style` field (integer 1~6) 2. **Executive Summary** — Deep blue title bar (`#1F4E79`) background + white text + body indent 3. **Table-Style TOC** — Deep blue title bar + three-column entries (number/chapter/page) 4. **Colorful Chapter Headings**: - H1: Full-row deep navy background `#1F4E79` + white text Microsoft YaHei - H2: Medium blue background `#2E75B6` + white text - H3: Light blue background `#D6E4F0` + dark blue text + `▌` left bar 5. **Key Callout Boxes** — Auto-detect 【关键】【注意】【优势】【风险】【数据】 tags, render as color cards (background/white text/border) 6. **Styled Tables** — Header deep navy background `#1F4E79` + white text + alternating row colors (`#DEEAF6` / `#FFFFFF`) --- ## Cover Styles (6 Types) Cover style specified via `cover_style` field in `plan.json` (integer, 1~6): | # | Style Name | Features | Recommended For | |---|------------|----------|-----------------| | 1 | Classic Government | Deep navy top bar + gold accents | Government/state enterprise approval | | 2 | Modern Minimalist | Left blue heavy block + right info | Tech/business reports | | 3 | Business Elegant | Burgundy + centered progression | Consulting/investment bank reports | | 4 | Tech Digital | Deep ocean blue fill + large white title | Internet/digital projects | | 5 | Chinese Traditional | Forbidden City red + rice paper cream background | Traditional culture/state enterprise | | 6 | Full Immersive | Deep ocean blue fill + large white title | Digital/tech projects | > **Note**: `cover_style` value is integer (e.g., `4`), code automatically converts to string for comparison. --- ## CLI Command Reference | Command | Description | |---------|-------------| | `python integrate_report.py` | Generate integrated report (full) | | `python integrate_report.py convert-batch` | Batch convert to docx | | `python integrate_report.py convert-one <in> <out>` | Single chapter to docx | | `python integrate_report.py check` | Consistency review | | `python integrate_report.py glossary` | Glossary generation/update | | `python integrate_report.py ref show` | View reference materials | | `python integrate_report.py ref clear` | Clear reference materials | | `python integrate_report.py preview [chapter prefix]` | Preview chapter summary | | `python integrate_report.py feishu-search <query>` | Search Feishu knowledge base | | `python parallel_tracker.py show` | View writing progress | | `python parallel_tracker.py wait` | Block & monitor (Ctrl+C to stop) | | `python parallel_tracker.py clear` | Clear tracking state | > **Switching cover style**: Edit `cover_style` field (integer 1~6) in `F:/agent/chapters/plan.json`, then regenerate. > After modifying code: delete `.pyc` files under `__pycache__` + `content_hashes.json` to force rebuild. --- ## State Files | File | Description | |------|-------------| | `F:/agent/chapters/plan.json` | Chapter metadata | | `F:/agent/chapters/glossary.json` | Terminology table | | `F:/agent/chapters/reference_material.txt` | Raw reference materials | | `F:/agent/chapters/plan_outline_snapshot.md` | Outline snapshot | | `F:/agent/chapters/content_hashes.json` | Incremental cache (delete to force rebuild) | | `F:/agent/chapters/writing_tracker.json` | Parallel progress tracking | | `F:/agent/chapters/config.json` | Cover style and other config | --- ## Critical Rules ### Markdown Table Format (Sub-Agents Must Follow) See `references/table_format_guide.md` for full spec Key points: - Separator row must be `|---|---|---|` (leading/trailing `|` required) - All rows must have same column count as header - Cell content should avoid containing `|` (use `～` or `-` for ranges) ### Force Rebuild (Must Do Both Steps After Code Changes) After modifying `integrate_report.py`, must delete both files for new code to take effect: ```bash # 1. Delete .pyc cache (required after code changes) del "C:\Users\Administrator\AppData\Roaming\LobsterAI\SKILLs\long-doc-agent\__pycache__\integrate_report.cpython-311.pyc" # 2. Delete incremental hash (or incremental mode skips everything) del F:\agent\chapters\content_hashes.json # 3. Regenerate python integrate_report.py ``` ### Known Bugs Fixed (For Reference) See `references/bug_fix_guide.md`, including: - `_flush_table` not calling `_parse_md_table` causing character-by-character table splitting - `cover_style` integer vs string comparison preventing cover from applying - `eval` RGB color assignment type error - `.pyc` cache causing new code to not take effect - `RGBColor` using index access `rgb[0]/rgb[1]/rgb[2]` instead of `.red/.green/.blue` - `add_cover()` setting `section.margin=0` causing body text to have no margins - `PermissionError` when docx file is open in WPS → auto-add `_v2` suffix - `write` tool has 50KB line limit → large scripts must be written in chunks --- ## References | File | Content | |------|---------| | `references/phase0_guide.md` | Phase 0 requirements confirmation full flow & scripts | | `references/phase1_guide.md` | Planner full prompt template & plan.json format | | `references/phase2_guide.md` | Sub-Agent full prompt template (incl. table format warnings) | | `references/table_format_guide.md` | Markdown table format spec, common errors & examples | | `references/bug_fix_guide.md` | Bug troubleshooting & forced rebuild procedures |

path: parallel_tracker.py
content: """
parallel_tracker.py
===================
多子Agent并行撰写可视化追踪模块

工作原理：
1. 主Agent使用 sessions_spawn 并行启动多个子Agent
2. 每个子Agent启动后向 TRACKER_FILE 写入自己的状态
3. 主Agent周期性地读取 TRACKER_FILE 并渲染可视化表格

使用方式：
  from parallel_tracker import Tracker, update_chapter_status

  # 子Agent端：启动时注册
  tracker = Tracker()
  tracker.register(seq="04", title="系统架构设计", batch="B")
  tracker.update(seq="04", phase="writing", progress=50, note="撰写功能模块...")

  # 子Agent端：完成后标记
  tracker.update(seq="04", phase="done", progress=100)
"""

import json, os, time, sys, threading
from datetime import datetime
from typing import Dict, List, Optional, Any
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path

# ============ 配置 ============
CHAPTERS_DIR = 'F:/agent/chapters'
TRACKER_FILE = f'{CHAPTERS_DIR}/writing_tracker.json'

# ============ 追踪器 ============

_GLOBAL_TRACKER: Optional['Tracker'] = None
_GLOBAL_LOCK = threading.Lock()


class Tracker:
    """多子Agent并行撰写状态追踪器（线程安全单例）"""

    def __init__(self, tracker_file: str = TRACKER_FILE):
        self.tracker_file = tracker_file
        self._ensure_file()

    @staticmethod
    def get_instance(tracker_file: str = TRACKER_FILE) -> 'Tracker':
        """获取单例实例（线程安全）"""
        global _GLOBAL_TRACKER
        if _GLOBAL_TRACKER is None:
            with _GLOBAL_LOCK:
                if _GLOBAL_TRACKER is None:
                    _GLOBAL_TRACKER = Tracker(tracker_file)
        return _GLOBAL_TRACKER

    def _ensure_file(self):
        if not os.path.exists(self.tracker_file):
            self._write({})

    def _read(self) -> Dict[str, Any]:
        with _GLOBAL_LOCK:
            try:
                with open(self.tracker_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            except Exception:
                return {}

    def _write(self, data: Dict[str, Any]):
        with _GLOBAL_LOCK:
            with open(self.tracker_file, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)

    def register(self, seq: str, title: str, batch: str = "", agent_id: str = ""):
        """子Agent启动时注册"""
        data = self._read()
        data[seq] = {
            "seq": seq,
            "title": title,
            "batch": batch,
            "agent_id": agent_id,
            "phase": "registered",  # registered | outline | writing | reviewing | done | error
            "progress": 0,
            "note": "已注册，等待启动...",
            "started_at": datetime.now().strftime('%H:%M:%S'),
            "updated_at": datetime.now().strftime('%H:%M:%S'),
        }
        self._write(data)
        return self

    def update(self, seq: str, phase: str, progress: int = None,
                note: str = "", error: str = ""):
        """
        更新子Agent撰写状态
        phase: registered | outline | writing | reviewing | done | error
        progress: 0-100
        """
        data = self._read()
        if seq not in data:
            # 未注册，自动注册
            data[seq] = {"seq": seq, "title": seq, "batch": ""}
        entry = data[seq]
        entry["phase"] = phase
        if progress is not None:
            entry["progress"] = progress
        if note:
            entry["note"] = note
        if error:
            entry["error"] = error
        entry["updated_at"] = datetime.now().strftime('%H:%M:%S')
        self._write(data)
        return self

    def mark_done(self, seq: str, note: str = "已完成"):
        return self.update(seq, phase="done", progress=100, note=note)

    def mark_error(self, seq: str, error: str):
        return self.update(seq, phase="error", note="出错", error=error)

    def get_status(self) -> Dict[str, Any]:
        return self._read()

    def clear(self):
        """清空追踪状态（每批次开始前调用）"""
        self._write({})

    def get_summary(self) -> Dict[str, int]:
        data = self._read()
        phases = {}
        for entry in data.values():
            p = entry.get("phase", "unknown")
            phases[p] = phases.get(p, 0) + 1
        return phases


# ============ 可视化渲染 ============

TRACKER_FILE_FOR_PRINT = TRACKER_FILE  # 模块级引用


def _progress_bar(progress: int, width: int = 12) -> str:
    """渲染进度条：▓░░░░░░░░░░"""
    filled = int(width * progress / 100)
    return '▓' * filled + '░' * (width - filled)


def _phase_emoji(phase: str) -> str:
    emoji_map = {
        "registered": "⏳",
        "outline": "📋",
        "writing": "✍️",
        "reviewing": "🔍",
        "done": "✅",
        "error": "❌",
    }
    return emoji_map.get(phase, "⚪")


def render_progress_table(tracker_file: str = TRACKER_FILE) -> str:
    """
    渲染当前并行撰写状态表格

    返回格式：
    ╔══════════════════════════════════════════════════════════════╗
    ║  📊 多子Agent并行撰写进度监控                                ║
    ╠══════════════════════════════════════════════════════════════╣
    ║  04 系统架构设计   ✍️  writing  ▓▓▓▓▓▓░░░░  50%  撰写功能模块... ║
    ║  05 技术路线       ✍️  writing  ▓▓▓░░░░░░░  25%  撰写技术选型... ║
    ║  06 功能模块设计   ⏳  registered  ─────────  0%   等待启动...   ║
    ╚══════════════════════════════════════════════════════════════╝
    """
    try:
        with open(tracker_file, 'r', encoding='utf-8') as f:
            data = json.load(f)
    except Exception:
        return "（追踪文件暂不可用）"

    if not data:
        return "（暂无并行撰写任务）"

    # 按 seq 排序
    sorted_entries = sorted(data.values(), key=lambda x: x.get('seq', '0'))

    # 计算全局进度
    total = len(sorted_entries)
    done = sum(1 for e in sorted_entries if e.get('phase') == 'done')
    errors = sum(1 for e in sorted_entries if e.get('phase') == 'error')
    overall_pct = int((done / total * 100)) if total > 0 else 0

    header = (
        f"╔══════════════════════════════════════════════════════════════╗\n"
        f"║  📊 多子Agent并行撰写进度监控  [{done}/{total} 完成"
        f"{' ❌' + str(errors) if errors > 0 else ''}]  总体 {overall_pct}%        ║\n"
        f"╠══════════════════════════════════════════════════════════════╣"
    )
    footer = "╚══════════════════════════════════════════════════════════════╝"

    rows = []
    for entry in sorted_entries:
        seq = entry.get('seq', '??').rjust(2)
        title = entry.get('title', '')[:14].ljust(14)
        phase_icon = _phase_emoji(entry.get('phase', ''))
        phase_name = entry.get('phase', '').rjust(10)
        progress = entry.get('progress', 0)
        bar = _progress_bar(progress)
        pct = str(progress).rjust(3) + '%'
        note = (entry.get('note', '') or '').strip()[:20].ljust(20)
        batch = entry.get('batch', '')
        batch_str = f"[{batch}] " if batch else "        "
        row = f"║  {seq} {batch_str}{title} {phase_icon} {phase_name} {bar} {pct}  {note} ║"
        rows.append(row)

    return '\n'.join([header] + rows + [footer])


def print_progress(tracker_file: str = TRACKER_FILE):
    """打印进度表格到标准输出（供 exec 调用）"""
    print(render_progress_table(tracker_file), flush=True)


# ============ 轮询监控器 ============

class ProgressMonitor:
    """
    定期轮询 tracker 文件并打印进度的监控器
    用于在子Agent并行撰写时，主session展示实时进度
    """

    def __init__(self, tracker_file: str = TRACKER_FILE, interval_sec: float = 8.0):
        self.tracker_file = tracker_file
        self.interval_sec = interval_sec
        self._running = False

    def start(self, duration_sec: float = None):
        """
        启动监控循环
        duration_sec: 监控持续秒数，None表示直到所有任务完成
        """
        self._running = True
        import time
        start = time.time()
        last_seen_done = set()

        print(f"[MONITOR] 启动进度监控（间隔{self.interval_sec}秒）", flush=True)

        while self._running:
            try:
                with open(self.tracker_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)

                entries = list(data.values())
                if not entries:
                    time.sleep(self.interval_sec)
                    continue

                # 检查是否全部完成
                done_seqs = {e['seq'] for e in entries if e.get('phase') == 'done'}
                error_seqs = {e['seq'] for e in entries if e.get('phase') == 'error'}

                # 打印进度
                os.system('cls' if os.name == 'nt' else 'clear')
                print(render_progress_table(self.tracker_file), flush=True)

                # 新完成任务时提示
                new_done = done_seqs - last_seen_done
                if new_done:
                    print(f"\n✅ 新完成：第 {[e['seq'] for e in entries if e['seq'] in new_done]} 章", flush=True)
                last_seen_done = done_seqs

                # 检查是否全部结束
                all_done = len(done_seqs) + len(error_seqs) == len(entries)
                if all_done:
                    print(f"\n[MONITOR] 所有章节撰写完成！", flush=True)
                    break

                # 检查超时
                if duration_sec and (time.time() - start) >= duration_sec:
                    print(f"\n[MONITOR] 监控超时（{duration_sec}秒）", flush=True)
                    break

                time.sleep(self.interval_sec)

            except Exception as e:
                print(f"[MONITOR] 轮询异常: {e}", flush=True)
                time.sleep(self.interval_sec)

    def stop(self):
        self._running = False


# ============ 子Agent端辅助函数 ============

def get_tracker() -> Tracker:
    """获取Tracker单例（子Agent端推荐使用）"""
    return Tracker.get_instance()


def chapter_register(seq: str, title: str, batch: str = ""):
    """子Agent启动时调用：注册章节撰写任务"""
    Tracker().register(seq=seq, title=title, batch=batch)


def chapter_update(seq: str, phase: str, progress: int = None, note: str = ""):
    """子Agent撰写过程中调用：更新进度"""
    Tracker().update(seq=seq, phase=phase, progress=progress, note=note)


def chapter_done(seq: str, note: str = "已完成"):
    """子Agent完成时调用：标记完成"""
    Tracker().mark_done(seq=seq, note=note)


def chapter_error(seq: str, error: str):
    """子Agent出错时调用：标记错误"""
    Tracker().mark_error(seq=seq, error=error)


# ============ CLI 入口 ============

if __name__ == '__main__':
    if len(sys.argv) >= 2:
        cmd = sys.argv[1]
        tracker = Tracker()

        if cmd == 'show' or len(sys.argv) == 2:
            print(render_progress_table())

        elif cmd == 'clear':
            tracker.clear()
            print("追踪状态已清空")

        elif cmd == 'status':
            summary = tracker.get_summary()
            print(f"当前状态: {summary}")
            total = sum(summary.values())
            done = summary.get('done', 0)
            print(f"进度: {done}/{total} 完成")

        elif cmd == 'wait':
            # 阻塞监控模式
            import time
            print("开始监控... Ctrl+C 停止")
            try:
                while True:
                    os.system('cls' if os.name == 'nt' else 'clear')
                    print(render_progress_table())
                    time.sleep(8)
            except KeyboardInterrupt:
                print("\n监控已停止")

        elif cmd == 'register' and len(sys.argv) >= 4:
            _, _, seq, title, *rest = sys.argv
            batch = rest[0] if rest else ""
            tracker.register(seq, title, batch)
            print(f"已注册：第{seq}章 {title} [{batch}]")

        elif cmd == 'update' and len(sys.argv) >= 4:
            _, _, seq, phase, *rest = sys.argv
            progress = int(restr[0]) if rest and rest[0].isdigit() else None
            note = rest[1] if len(restr := rest) > 1 else ""
            tracker.update(seq, phase, progress, note)
            print(f"已更新：第{seq}章 {phase} {progress or ''}% {note}")

        elif cmd == 'done' and len(sys.argv) >= 3:
            seq = sys.argv[2]
            tracker.mark_done(seq)
            print(f"已标记完成：第{seq}章")

    else:
        print(render_progress_table())


path: references/bug_fix_guide.md
content: # Bug Troubleshooting & Forced Rebuild

## Fixed: Table Rendering Distortion

### Problem Description

In the generated docx, tables have only 1 column with content split character-by-character; or column count far exceeds expectation (e.g., 4-column table becomes 60+ columns).

### Root Cause

Bug in `_flush_table` function in `integrate_report.py`:

```python
# ❌ Buggy code (early v3)
def _flush_table(doc, pending_table):
    if pending_table:
        _add_table_to_doc(doc, pending_table)   # ← Passing raw string list!
        pending_table.clear()
```

- `pending_table` stores `['| Col1 | Col2 | Col3 |', ...]` (string list)
- `_add_table_to_doc` uses `max(len(r) for r in rows)` to calculate column count
- Calling `len()` on a string gives character count (17), not cell count (3)
- Result: 4-column table → 63 columns → each character occupies one cell → completely distorted

### Fix

```python
# ✅ Correct code (current version)
def _flush_table(doc, pending_table):
    if pending_table:
        parsed_rows = _parse_md_table(pending_table)  # ← NEW: parse to 2D array first
        _add_table_to_doc(doc, parsed_rows)           # ← Pass parsed array
        pending_table.clear()
```

### Validation

```python
from docx import Document
doc = Document('F:/agent/整合报告.docx')
for t in doc.tables:
    print(f'{len(t.rows)} rows x {len(t.columns)} cols')
    # Normal column count: 2~8 columns
    # If you see 15+, 30+, 60+ columns → Bug still exists
```

---

## Fixed: Cover Style Comparison Type Error

### Problem Description

`cover_style` in `plan.json` is an integer (e.g., `4`), but code compares as string, causing cover to always take the generic branch — styled cover doesn't apply.

### Root Cause

```python
# ❌ Buggy code
cover_style = plan.get('cover_style', '4')
if cover_style == '4':   # Integer 4 != String '4', always False
```

### Fix

```python
# ✅ Correct code
cover_style = str(plan.get('cover_style', '4'))
if cover_style == '4':   # String comparison, works correctly
```

---

## Fixed: RGB Color Assignment Error

### Problem Description

Using `eval(f'0x{hex_color}')` to assign color causes `run.font.color.rgb` to receive an integer instead of an `RGBColor` object, throwing an error.

### Root Cause

```python
# ❌ Buggy code
run.font.color.rgb = eval(f'0x{H1_TEXT}')  # eval('0xFFFFFF') → 16777215 (int)
# ValueError: rgb color value must be RGBColor object, got <class 'int'>
```

### Fix

```python
# ✅ Correct code
from docx.shared import RGBColor  # ← Must import
run.font.color.rgb = RGBColor.from_string(H1_TEXT)
```

---

## Fixed: Incremental Cache Causing New Code to Not Take Effect

### Problem Description

After modifying core logic in `integrate_report.py` and regenerating, incremental mode skips all chapters.

### Root Cause

Python caches compiled `.pyc` files. After modifying `.py`, if cache isn't deleted, the imported code is still the old version. Also `content_hashes.json` causes rewrite skipping.

### Fix

After every code change, do both:

```bash
# 1. Delete .pyc cache
del "C:\Users\Administrator\AppData\Roaming\LobsterAI\SKILLs\long-doc-agent\__pycache__\integrate_report.cpython-311.pyc"

# 2. Delete incremental hash
del F:\agent\chapters\content_hashes.json

# 3. Regenerate
python integrate_report.py
```

---

## Forced Rebuild

### Steps

```bash
# 1. Delete incremental cache and old report
del F:\agent\chapters\content_hashes.json
del F:\agent\整合报告.docx

# 2. Delete .pyc cache (required after code changes)
del "C:\Users\Administrator\AppData\Roaming\LobsterAI\SKILLs\long-doc-agent\__pycache__\integrate_report.cpython-311.pyc"

# 3. Regenerate
cd "C:\Users\Administrator\AppData\Roaming\LobsterAI\SKILLs\long-doc-agent"
python integrate_report.py
```

---

## New: RGBColor Property Access (python-docx 1.2.0)

### Problem Description

Error when running `make_docx.py`: `AttributeError: 'RGBColor' object has no attribute 'red'`

### Root Cause

python-docx 1.2.0's `RGBColor` object doesn't support `.red / .green / .blue` property access; must use index access.

### Fix

```python
# ❌ Wrong
'{:02X}{:02X}{:02X}'.format(rgb.red, rgb.green, rgb.blue)

# ✅ Correct
'{:02X}{:02X}{:02X}'.format(rgb[0], rgb[1], rgb[2])
```

---

## New: Cover Function Must Not Modify Global Page Margins

### Problem Description

Code in `add_cover()` setting `section.left_margin=0` etc. propagates to all pages after the cover, causing body text to fill the entire page (no margins).

### Root Cause

Word's Section properties persist across pages; margins set on the cover affect the entire document.

### Fix

Use a full-page table for the background color in the cover, **do not** modify any section margin properties. Set body margins once in `main()`.

```python
# ❌ Wrong
def add_cover(doc):
    sec = doc.sections[0]
    sec.left_margin=Inches(0)   # ← Affects all pages!
    ...

# ✅ Correct: only add table, don't touch section
def add_cover(doc):
    tbl_ = doc.add_table(rows=1, cols=1)
    cell = tbl_.rows[0].cells[0]
    # Just fill the table across the full page, don't touch section margin
```

---

## New: Auto-Rename When File Is Held Open

### Problem Description

If the generated docx file is already open in WPS/Word, saving again raises `PermissionError`.

### Fix

Add `_v2` suffix to filename (auto-increment), avoiding conflict with open files. In code:

```python
out_name = 'Hospital_Personnel_Location_Management_System_Proposal.docx'
out_path = os.path.join(out_dir, out_name)
if os.path.exists(out_path):
    # File exists, add v2/v3... to avoid conflict
    base, ext = os.path.splitext(out_name)
    counter = 2
    while os.path.exists(os.path.join(out_dir, f'{base}_v{counter}{ext}')):
        counter += 1
    out_name = f'{base}_v{counter}{ext}'
    out_path = os.path.join(out_dir, out_name)
```

---

## New: write Tool Has 50KB Line Limit — Large Scripts Must Use Chunked Writing

### Problem Description

Using `write` tool to write Python scripts > ~50KB or ~2000 lines results in truncated content (only partial code written).

### Root Cause

The write tool has a per-file size limit.

### Fix

Write large scripts in two steps:

```python
# Step 1: Write main file (excluding trailing main() call)
with open('make_docx.py', 'w', encoding='utf-8') as f:
    f.write(main_content)  # Main content

# Step 2: Append trailing portion
closing = """
def main():
    ...  # Trailing content

if __name__ == '__main__':
    main()
"""
with open('make_docx.py', 'a', encoding='utf-8') as f:
    f.write(closing)
```

---

## Other Common Issues

### Symptom: Table content all shows as `|`

`_parse_md_table` was not called. Confirm `_flush_table` contains `parsed_rows = _parse_md_table(pending_table)`.

### Symptom: Incremental mode skips modified chapters

Delete `content_hashes.json` to force full rebuild.

### Symptom: Sub-Agent-written txt contains garbled text

Sub-Agent output used wrong encoding. Ensure sub-agents save with `encoding='utf-8'`.


path: references/phase0_guide.md
content: # Phase 0: Requirements Confirmation Full Flow

## Trigger Conditions

User's first writing request ("I want to write xxx"/"help me write a feasibility report"/"write a xxx report")

## Four-Step Confirmation Flow

### Step 1 — Confirm Writing Topic

```
Please tell me the core information for this document:

1. What is the document topic?
   (e.g., XX City People's Hospital Medical Asset Refined Management Solution)
2. What type of document is it?
   (e.g., Feasibility Study Report / Technical Proposal / Business Plan)
3. Who is the primary audience?
   (e.g., Hospital Management / Superior Regulatory Authority / Investors)
4. Overall style?
   (e.g., Professional & Rigorous / Concise & Clear)
5. Any special requirements or constraints?
   (e.g., Must include budget section / No more than 10 chapters, etc.)
```

### Step 2 — Confirm Writing Background

```
Please provide or describe the background information for this project/topic:

1. What is the project background?
   (e.g., Current hospital asset management status, problems faced)
2. What are the construction goals?
   (e.g., Improve asset utilization rate, control costs)
3. Any specific industry background?
   (e.g., National policies, industry trends)
```

### Step 3 — Provide Reference Materials (Most Important)

```
Please provide reference materials related to this writing task (provide at least one):

A. Upload file: Send local file path or paste content directly
B. Feishu document: Provide document name or link (I will search via RAG)
C. Paste directly: Send reference text directly to this assistant
D. Not provided for now (skip, write using general background knowledge)

⚠️ Strongly recommend providing reference materials!
The more reference material, the more business-aligned the content, the higher the output quality.
Reference materials will be injected as the primary RAG knowledge source into each chapter's writing context.
```

### Step 4 — Outline Confirmation

After planner outputs the outline, display it to the user for confirmation:

```
📋 Planning outline generated. Please confirm the following chapter structure:

Project: XX City People's Hospital Medical Asset Full Lifecycle Refined Management Solution
Type: Feasibility Study Report | Audience: Hospital Management

Chapter Outline:
1. Chapter 01 Project Overview (Batch A, ~2500 words)
2. Chapter 02 Construction Background & Necessity (Batch A, ~3000 words)
...

Please confirm:
 A. Outline OK, start writing
 B. Need to adjust outline (please specify which chapters need modification/addition/deletion)
 C. Cancel this writing task
```

## Saving Reference Materials

After user confirmation, save reference materials to `F:/agent/chapters/reference_material.txt`:
```python
with open('F:/agent/chapters/reference_material.txt', 'w', encoding='utf-8') as f:
    f.write(reference_text)
```


path: references/phase1_guide.md
content: # Phase 1: Planner Full Prompt Template

## Execution Steps

1. Load `F:/agent/chapters/reference_material.txt` summary (first 3000 characters) as `reference_summary`
2. Replace `{xxx}` placeholders in the template below with actual values
3. Write output to `F:/agent/chapters/plan.json`

## Prompt Template

```
You are a professional project planner. The user needs to write a 【{doc_type}】 on the topic of "{topic}".

## User-Provided Background Information
{background}

## Reference Material Summary (Priority Reference)
{reference_summary}

Please complete the following tasks:
1. Create a detailed document outline (down to H3 headings)
2. Annotate core writing points for each chapter
3. Identify RAG search keywords for each chapter (≤3 per chapter)
4. Evaluate complexity of each chapter, mark key chapters
5. Identify chapter dependencies (which chapters must be completed before others can be written)

**Chapter Dependency Rules**:
- Type 1 (no dependencies, write first): Overview, Background, Current Analysis, Technology Selection
- Type 2 (depends on Type 1): Overall Design, Detailed Function Design
- Type 3 (depends on several preceding chapters): Implementation Plan, Testing Plan, Deployment Plan
- Type 4 (can write independently or last): Training Plan, Acceptance Plan, Appendices, Conclusion

**Reference Materials Prohibition**
Actively exclude content unrelated to the topic during planning (e.g., infusion monitoring systems, etc.).

Write the following structured information to F:/agent/chapters/plan.json:
{
  "project_name": "Project Name",
  "doc_type": "Document Type",
  "chapters": [
    {
      "seq": "01",
      "title": "Chapter Title",
      "brief": "Writing Points",
      "feishu_keywords": ["k1", "k2"],
      "web_keywords": ["k1", "k2"],
      "word_count": 3000,
      "batch": "A",
      "dependencies": [],
      "status": "pending"
    }
  ]
}
```

## plan.json Field Descriptions

| Field | Description |
|-------|-------------|
| `seq` | Chapter sequence number, 2-digit string ("01", "02") |
| `title` | Chapter title |
| `brief` | Core writing points (50-100 characters) |
| `feishu_keywords` | Feishu knowledge base search keywords, max 3 |
| `web_keywords` | Web search keywords, max 3 |
| `word_count` | Target word count (body text, excluding headings) |
| `batch` | Batch label ("A"/"B"/"C", same batch can be written in parallel) |
| `dependencies` | Dependent chapter seq list, e.g. `["01", "02"]` |
| `status` | Status: `pending`/`writing`/`txt_done`/`confirmed` |

## Post-Execution Actions

```bash
# 1. Generate initial glossary (extracted from reference materials)
python integrate_report.py glossary

# 2. Save outline snapshot
python integrate_report.py save-outline

# 3. Display outline to user for confirmation
```


path: references/phase2_guide.md
content: # Phase 2: Sub-Agent Full Prompt Template

## Template Variable Descriptions

| Variable | Source |
|----------|--------|
| `{seq}` | seq field of this chapter in plan.json |
| `{title}` | title field of this chapter in plan.json |
| `{batch}` | batch field of this chapter in plan.json |
| `{topic}` | Document topic |
| `{audience}` | Target audience |
| `{style}` | Overall style |
| `{word_count}` | word_count field of this chapter in plan.json |
| `{reference_summary}` | Reference material summary (first 3000 characters) |
| `{glossary_summary}` | Glossary summary (first 30 entries) |
| `{dependency_chapters}` | Title list of dependent chapters |
| `{chapter_brief}` | brief field of this chapter in plan.json |
| `{feishu_keywords}` | feishu_keywords from plan.json |
| `{web_keywords}` | web_keywords from plan.json |
| `{index}` | 2-digit sequential number (01, 02...) |
| `{short_name}` | Chapter short name (used in filenames) |

## Sub-Agent Prompt (Full Version)

```python
import sys
sys.path.insert(0, r'C:\Users\Administrator\AppData\Roaming\LobsterAI\SKILLs\long-doc-agent')
from parallel_tracker import chapter_register, chapter_update, chapter_done

chapter_register(seq='{seq}', title='{title}', batch='{batch}')

You are a professional document writing expert, responsible for writing the 【{chapter_title}】 chapter of the feasibility report.

## Basic Information
- Document Topic: {topic}
- Target Audience: {audience}
- Overall Style: {style}
- This Chapter's Word Target: {word_count} words

## Reference Materials (Priority Use)
{reference_summary}

## Glossary Reference (Must Use Consistent Terminology)
{glossary_summary}

## Dependencies
This chapter depends on the following completed chapters:
{dependency_chapters}

## This Chapter's Writing Points
{chapter_brief}

## RAG Search (Supplementary Reference)
- Feishu Knowledge Base: keywords {feishu_keywords}
- Web Search (backup): keywords {web_keywords}

## Writing Requirements
1. Content must be professional and rigorous, conforming to feasibility report standards
2. Prioritize citing facts and data from reference materials
3. Terminology usage must be consistent with the glossary
4. Word count: approximately {word_count} words
5. Output format: Markdown

## ⚠️ Markdown Table Format (Must Follow)
When inserting tables, you MUST strictly follow this format, otherwise tables will be distorted in docx conversion:

Correct format:
| Col1 | Col2 | Col3 |
|---|---|---|
| Content1 | Content2 | Content3 |

Key points:
- Separator row format must be `|---|---|---|` (leading/trailing `|` required)
- All rows must have the same column count as the header — mismatch causes column displacement
- Cell content should avoid containing `|` (use `～` or `-` for ranges)

## Progress Update
After completing each ## H2 section heading, call:
chapter_update(seq='{seq}', phase='writing', progress=30, note='Writing in progress...')

## Output: Generate Plain Text .txt Only
After completing the writing:
1. Save to F:/agent/chapters/{index:02d}-{short_name}.txt
2. Call chapter_done(seq='{seq}', note='Completed')
3. Update this chapter's status to 'txt_done' in plan.json
```

## Per-Batch Execution Flow (Main Agent Side, Fully Automatic)

```python
# 1. Display outline/current status (display only, no user confirmation)
print(f"Current batch: Batch {label}")
print(f"Chapters to write: {chapters_list}")
print(f"Estimated parallelism: {n} chapters")

# 2. Clear previous batch tracking state
from parallel_tracker import Tracker
Tracker().clear()

# 3. Parallel launch sub-agents (≤5 per batch, automatically execute all batches)
for subagent_task in batch_tasks:
    sessions_spawn(
        task=subagent_task,
        runtime="subagent",
        runTimeoutSeconds=300,
        mode="run"
    )

# 4. Monitor progress in background (automatically wait for this batch to complete)
# python parallel_tracker.py wait

# 5. After this batch completes, automatically proceed to next batch (no user confirmation)
# If this is the last batch, automatically execute:
from integrate_report import batch_convert_txt_to_docx
batch_convert_txt_to_docx(txt_dir='F:/agent/chapters', max_concurrent=8)
```

## Batch Completion Notification

WeChat notification is automatically sent after each batch completes, no manual intervention needed. If any chapter needs modification, you can notify the main agent at any time (supports small changes via direct .txt editing, or large changes via full chapter regeneration).


path: references/table_format_guide.md
content: # Markdown Table Format Specification

Sub-agents must strictly follow this specification when inserting tables in `.txt` files. Incorrect format causes table distortion during docx conversion.

## Correct Format

```
| Col1 | Col2 | Col3 |
|---|---|---|
| Content1 | Content2 | Content3 |
| Content4 | Content5 | Content6 |
```

## Six Key Rules

1. **Separator row must include leading and trailing `|`**
   - ✅ Correct: `|---|---|---|`
   - ❌ Wrong: `---|---|---` (missing leading/trailing `|`)
   - ❌ Wrong: `|---|:---|:---|` (missing leading/trailing `|` on separator row)

2. **All rows (including data rows) must have leading and trailing `|`**
   - Each row format: `| Cell1 | Cell2 | Cell3 |`

3. **All rows must have the same column count as the header**
   - If header has 4 columns, all data rows must also have 4 columns
   - Mismatch causes column displacement in docx

4. **Separator row only allows `-`, `:`, `|` and spaces**
   - ✅ `|---|`, `| :--- |` (alignment markers)
   - ❌ `|===|` (`=` not allowed)
   - ❌ `|--|--|` (missing leading/trailing `|`)

5. **Cell content must not contain line breaks**
   - Cell content must be completed on a single line

6. **Cell content should avoid containing `|` character**
   - Use `～` or `-` for ranges: `25—45` not `25|45`
   - If `|` must be included, escape it (not recommended)

## Common Error Examples

| Error Type | Wrong | Correct |
|------------|-------|---------|
| Missing leading/trailing `\|` | `\|---\|---\|---` | `\|---\|---\|---\|` |
| Inconsistent row/column count | `\|A\|B\|C\|` followed by `\|1\|2\|` (missing column) | `\|A\|B\|C\|` followed by `\|1\|2\| \|` |
| Separator row uses `=` | `\|====\|====\|` | `\|---\|---\|` |
| Cell contains `\|` | `\|25\|45\|` (range) | `\|25～45\|` |

## Recommended Symbols for Cell Content

| Purpose | Recommended Symbol | Example |
|---------|-------------------|---------|
| Numeric range | `～` or `—` | `25～45`, `25—45` |
| Percentage | `%` | `30%` |
| Rating | `★` (avoid `\|`) | `★★★☆☆` |
| Notes/Remarks | Write directly | `Including equipment maintenance service` |

## Validation Method

After generating docx, use this command to check if column counts are reasonable (normally 2~8 columns):

```python
from docx import Document
doc = Document('F:/agent/整合报告.docx')
for t in doc.tables:
    print(f'{len(t.rows)} rows x {len(t.columns)} cols')
    # Column count > 15 usually indicates table format error
```

## Why Format Errors Cause Distortion

`_add_table_to_doc` internally uses `max(len(r) for r in rows)` to calculate column count:
- After correct parsing: `rows[0] = ['Col1', 'Col2', 'Col3']`, `len = 3`
- When raw string is passed: `rows[0] = '| Col1 | Col2 | Col3 |'`, `len = 17` (character count)

17 columns vs 3 columns → each character occupies one cell → table completely distorted.


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)