Skill: karasawayikiho/openclawcontinuouswork (version 1.0.0)

--- name: openclaw-continuous-work description: 全面优化 OpenClaw 对话体验并强化任务闭环执行。Use when user asks to 优化, 工作, 项目, 持续工作, 不要停, 继续做, 继续工作, 或希望助手接收指令后持续推进直到完成。Also use when the user asks for complete optimization tasks rather than partial fixes. --- # OpenClaw Continuous Work ## Goal - 连续推进：接到指令后持续执行直到完成。 - 优化闭环：优化任务必须全链路落地并回归验证。 - 稳定反馈：里程碑 + 时间触发进度汇报，避免沉默或刷屏。 ## Rule Map - 规则总览（自动索引）：`References/ReferenceMap.md` - 模块化规范：`References/ModuleSystem.md` - 模块加载顺序配置：`References/ModuleOrder.json` ## Core Modules - 通用连续执行规则：`References/GeneralRules.md` - 持续执行强约束：`References/ContinuousExecutionDirective.md` - 优化任务专项规则：`References/OptimizationRules.md` - 优化指令原文基线：`References/OptimizationDirective.md` - 汇报模板：`References/ReportingTemplate.md` - 优化清单：`References/OptimizationChecklist.md` - 验收模板：`References/AcceptanceTemplate.md` - 质量评分：`References/QualityRubric.md` ## Scripts - 一键优化流水线：`Scripts/RunOptimizationPipeline.py` - 用法：`python Scripts/RunOptimizationPipeline.py <target_path>` - 作用：串联执行命名巡检、内容/链接巡检、索引重建并输出汇总结果。 - 命名规范巡检：`Scripts/NamingAudit.py` - 用法：`python Scripts/NamingAudit.py <target_path> --json` - 作用：扫描命名不符合“单词首字母大写”规则的文件/文件夹并给出建议。 - 模块顺序校验：`Scripts/ValidateModuleOrder.py` - 用法：`python Scripts/ValidateModuleOrder.py` - 作用：校验 `References/ModuleOrder.json`（缺失模块、重复项、冲突项），输出 `ModuleOrderReport.md/json`。 - 模块索引重建：`Scripts/BuildReferenceMap.py` - 用法：`python Scripts/BuildReferenceMap.py` - 作用：自动重建 `References/ReferenceMap.md`，让新增 MD 模块即时纳入索引。 - 模块依赖图构建：`Scripts/BuildModuleGraph.py` - 用法：`python Scripts/BuildModuleGraph.py` - 作用：自动生成 `References/ModuleGraph.md` 与 `References/ModuleGraph.json`。 - 规则冲突巡检：`Scripts/DetectRuleConflicts.py` - 用法：`python Scripts/DetectRuleConflicts.py` - 作用：自动生成 `References/ConflictReport.md` 与 `References/ConflictReport.json`。 - 内容去重与链接巡检：`Scripts/ContentLinkAudit.py` - 用法：`python Scripts/ContentLinkAudit.py <target_path> --json` - 作用：检测重复段落与失效 Markdown 链接，支持持续精简与联动。 - 编码规范化：`Scripts/NormalizeEncoding.py` - 用法：`python Scripts/NormalizeEncoding.py` - 作用：统一文本文件为 UTF-8（无 BOM）+ LF，降低写入与解析报错风险。 ## Maintainer Notes - 新增场景优先写入 `References/`，保持本文件精简。 - 优先扩展：触发词、失败升级策略、完成判定与验收模板。

path: Scripts/BuildModuleGraph.py
content: #!/usr/bin/env python3
"""
BuildModuleGraph.py
Generate module dependency graph from markdown links in References/*.md
Outputs:
- References/ModuleGraph.md (human-readable)
- References/ModuleGraph.json (machine-readable)
"""

from __future__ import annotations

import json
import re
from pathlib import Path

REF_DIR = Path(__file__).resolve().parents[1] / "References"
GRAPH_MD = REF_DIR / "ModuleGraph.md"
GRAPH_JSON = REF_DIR / "ModuleGraph.json"

LINK_RE = re.compile(r"\[[^\]]+\]\(([^)]+\.md)\)", re.IGNORECASE)
SEE_ALSO_RE = re.compile(r"See also:\s*<([^>]+\.md)>", re.IGNORECASE)


def parse_links(text: str) -> list[str]:
    links = LINK_RE.findall(text)
    links += SEE_ALSO_RE.findall(text)
    return links


def build_graph() -> dict:
    modules = sorted(p.name for p in REF_DIR.glob("*.md") if p.name not in {"ModuleGraph.md", "ReferenceMap.md"})
    edges: dict[str, list[str]] = {m: [] for m in modules}

    for mod in modules:
        p = REF_DIR / mod
        text = p.read_text(encoding="utf-8", errors="ignore")
        deps: list[str] = []
        for raw in parse_links(text):
            name = Path(raw).name
            if name in edges and name != mod:
                deps.append(name)
        edges[mod] = sorted(set(deps))

    return {"modules": modules, "edges": edges}


def write_outputs(graph: dict) -> None:
    GRAPH_JSON.write_text(json.dumps(graph, ensure_ascii=False, indent=2), encoding="utf-8")

    lines = ["# Module Graph", "", "Auto-generated dependency graph between markdown modules.", "", "## Nodes"]
    for m in graph["modules"]:
        lines.append(f"- `{m}`")

    lines.append("")
    lines.append("## Edges")
    for src in graph["modules"]:
        deps = graph["edges"].get(src, [])
        if deps:
            lines.append(f"- `{src}` -> {', '.join(f'`{d}`' for d in deps)}")
        else:
            lines.append(f"- `{src}` -> (none)")

    lines.append("")
    lines.append("## Notes")
    lines.append("- Rebuild with: `python Scripts/BuildModuleGraph.py`")
    lines.append("- Pair with `BuildReferenceMap.py` after adding new modules.")

    GRAPH_MD.write_text("\n".join(lines) + "\n", encoding="utf-8")


def main() -> None:
    graph = build_graph()
    write_outputs(graph)
    print(f"Updated: {GRAPH_MD}")
    print(f"Updated: {GRAPH_JSON}")
    print(f"Modules: {len(graph['modules'])}")


if __name__ == "__main__":
    main()


path: Scripts/BuildReferenceMap.py
content: #!/usr/bin/env python3
"""
BuildReferenceMap.py
Auto-generate References/ReferenceMap.md so users can add new .md modules anytime.
Load ordering from References/ModuleOrder.json (configurable priority + exclude list).
"""

from __future__ import annotations

import json
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
REF_DIR = ROOT / "References"
MAP_FILE = REF_DIR / "ReferenceMap.md"
ORDER_FILE = REF_DIR / "ModuleOrder.json"

DEFAULT_EXCLUDE = {"ReferenceMap.md", "ModuleGraph.md", "ConflictReport.md"}
DEFAULT_PRIORITY = [
    "GeneralRules.md",
    "ContinuousExecutionDirective.md",
    "OptimizationRules.md",
    "OptimizationDirective.md",
    "OptimizationChecklist.md",
    "ReportingTemplate.md",
    "AcceptanceTemplate.md",
    "QualityRubric.md",
    "ModuleSystem.md",
]


def load_order_config() -> tuple[list[str], set[str]]:
    if not ORDER_FILE.exists():
        return DEFAULT_PRIORITY, set(DEFAULT_EXCLUDE)

    try:
        data = json.loads(ORDER_FILE.read_text(encoding="utf-8-sig"))
        prio = data.get("priority", DEFAULT_PRIORITY)
        excl = set(data.get("exclude", list(DEFAULT_EXCLUDE)))
        return list(prio), excl
    except Exception:
        return DEFAULT_PRIORITY, set(DEFAULT_EXCLUDE)


def collect_modules() -> list[str]:
    priority, exclude = load_order_config()
    mods = [p.name for p in REF_DIR.glob("*.md") if p.name not in exclude]
    mods_sorted = sorted(mods)
    ordered = [m for m in priority if m in mods_sorted]
    rest = [m for m in mods_sorted if m not in ordered]
    return ordered + rest


def build_content(mods: list[str]) -> str:
    lines: list[str] = []
    lines.append("# Reference Map")
    lines.append("")
    lines.append("Auto-generated module index. New `References/*.md` files are included after running `python Scripts/BuildReferenceMap.py`.")
    lines.append("Ordering can be configured by `References/ModuleOrder.json`.")
    lines.append("")
    lines.append("## Canonical Flow")
    lines.append("1. Read `GeneralRules.md` for baseline continuous execution behavior.")
    lines.append("2. Apply `ContinuousExecutionDirective.md` when user enforces strong continuous-work constraints.")
    lines.append("3. For optimization tasks, apply `OptimizationRules.md` + `OptimizationDirective.md`.")
    lines.append("4. Use `OptimizationChecklist.md` during execution.")
    lines.append("5. Use `ReportingTemplate.md` for updates.")
    lines.append("6. Use `AcceptanceTemplate.md` + `QualityRubric.md` for closure.")
    lines.append("")
    lines.append("## Available Modules")
    for m in mods:
        lines.append(f"- `{m}`")
    lines.append("")
    lines.append("## Extending")
    lines.append("- Add a new `.md` file into `References/`.")
    lines.append("- (Optional) edit `References/ModuleOrder.json` for load priority.")
    lines.append("- Run `python Scripts/BuildReferenceMap.py`.")
    lines.append("- Commit and push.")
    lines.append("")
    return "\n".join(lines)


def main() -> None:
    mods = collect_modules()
    MAP_FILE.write_text(build_content(mods), encoding="utf-8")
    print(f"Updated: {MAP_FILE}")
    print(f"Modules: {len(mods)}")


if __name__ == "__main__":
    main()


path: Scripts/ContentLinkAudit.py
content: #!/usr/bin/env python3
"""
ContentLinkAudit.py
Audit markdown modules for:
1) duplicate paragraphs (possible repetition)
2) missing intra-repo markdown links in ReferenceMap.md
"""

from __future__ import annotations

import argparse
import json
import re
from pathlib import Path
from collections import defaultdict


def norm_text(s: str) -> str:
    s = s.strip()
    s = re.sub(r"\s+", " ", s)
    return s


def extract_paragraphs(md: str) -> list[str]:
    blocks = re.split(r"\n\s*\n", md)
    out = []
    for b in blocks:
        t = norm_text(b)
        if not t:
            continue
        if t.startswith("#"):
            continue
        if len(t) < 40:
            continue
        out.append(t)
    return out


def extract_md_links(md: str) -> list[str]:
    # [text](path)
    return re.findall(r"\[[^\]]+\]\(([^)]+\.md)\)", md, flags=re.IGNORECASE)


def scan(root: Path) -> dict:
    md_files = sorted(p for p in root.rglob("*.md") if ".git" not in p.parts)
    paragraph_index: dict[str, list[str]] = defaultdict(list)
    missing_links = []

    for f in md_files:
        text = f.read_text(encoding="utf-8", errors="ignore")
        rel = str(f.relative_to(root))

        for para in extract_paragraphs(text):
            paragraph_index[para].append(rel)

        for link in extract_md_links(text):
            target = (f.parent / link).resolve()
            if not target.exists():
                missing_links.append({"file": rel, "link": link})

    duplicates = []
    for para, files in paragraph_index.items():
        uniq = sorted(set(files))
        if len(uniq) > 1:
            duplicates.append({
                "files": uniq,
                "sample": para[:160] + ("..." if len(para) > 160 else "")
            })

    return {
        "root": str(root),
        "markdown_files": len(md_files),
        "duplicate_paragraph_groups": duplicates,
        "missing_links": missing_links,
        "duplicate_count": len(duplicates),
        "missing_link_count": len(missing_links),
    }


def main() -> None:
    ap = argparse.ArgumentParser()
    ap.add_argument("target", nargs="?", default=".")
    ap.add_argument("--json", action="store_true")
    args = ap.parse_args()

    root = Path(args.target).resolve()
    result = scan(root)

    if args.json:
        print(json.dumps(result, ensure_ascii=False, indent=2))
        return

    print(f"Root: {result['root']}")
    print(f"Markdown Files: {result['markdown_files']}")
    print(f"Duplicate Paragraph Groups: {result['duplicate_count']}")
    print(f"Missing Links: {result['missing_link_count']}")


if __name__ == "__main__":
    main()


path: References/AcceptanceTemplate.md
content: # Acceptance Template

## Objective
- 用户目标：<一句话>
- 验收标准：
  1) <标准1>
  2) <标准2>
  3) <标准3>

## Delivery Checklist
- [ ] 功能/任务主目标完成
- [ ] 关键路径验证通过
- [ ] 关联模块影响已检查
- [ ] 异常/边界场景已抽样验证
- [ ] 输出结果可复用（文档/脚本/配置）

## Verification Evidence
- 关键结果：<产物/命令输出/对比结果>
- 回归结果：<通过项/失败项>
- 风险残留：<无/具体项>

## Final Statement
- 结论：<已完成/部分完成/阻塞>
- 原因：<简述>
- 建议后续：<最多3条>


path: References/ConflictReport.json
content: {
  "module_count": 11,
  "conflict_groups": [],
  "count": 0
}

path: References/ConflictReport.md
content: # Conflict Report

Auto-generated potential rule conflict report (keyword heuristic).

- Modules scanned: 11
- Potential conflict groups: 0

## Results
- No potential conflicts detected by heuristic patterns.
## Notes
- This report is heuristic and may include false positives.
- Review flagged module pairs manually before changing rules.
- Rebuild with: `python Scripts/DetectRuleConflicts.py`


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