Skill: ldxs001/semantic-split (version 2.5.0)

--- name: semantic-split description: 语义拆分与智能规划技能。将自然语言拆分为结构化需求块，基于5W2H维度提取与约束标注增强语义理解，双视角推理整合为单一执行步骤，支持自增强json沉淀机制。 version: "2.5.0" author: wUwproject tags: - semantic-split - task-planning - json-accumulation - progressive-loading - 5w2h - constraint-annotation --- # semantic-split — 语义拆分与智能规划 将自然语言拆分为结构化需求块，基于 5W2H 维度提取与约束标注增强语义理解，双视角推理整合为单一执行步骤。 ## 触发场景 - 用户提出任务请求："帮我做..."、"我需要..."、"交给你了..." - 用户描述问题寻求帮助、表达需求、委托工作 - 简单问答和闲聊无需拆分 ## 核心能力 | # | 功能 | 说明 | |---|------|------| | 1 | **语义拆分** | 识别主语 → 划分块 → 提取目的/行为/动机 | | 2 | **5W2H维度提取** | 自动抽取7维度 + 缺失维度填默认值（按任务类型映射表） | | 3 | **约束强度标注** | 硬约束🔴/软约束🟡/无约束⚪ 三级标注 + 注意力锚定 | | 4 | **双视角推理** | 聚焦（保守）+ 发散（创新）内部推理 → 整合为单一执行步骤 | | 5 | **结构化输出** | 统一格式输出拆分结果（含约束标注），含确认询问 | | 6 | **渐进式加载** | 规则级/能力级 json 渐进匹配，未命中时模型思考 | | 7 | **自增强闭环** | 一次使用 → 沉淀 json → 下次复用 | | 8 | **json 管理工具** | `json_manager.py` CLI 统一管理能力级/规则级 json | ## 快速开始 ```bash python scripts/json_manager.py scan --keywords 制作 PPT 产品 # 扫描匹配 python scripts/json_manager.py categorize --threshold 5 # 归类统计 python scripts/json_manager.py create --type capability --name my_task_v1 # 创建 python scripts/json_manager.py generalize --input <path> --params "具体值=[占位符]" # 通用化 ``` > 知识库 JSON 存放于 `skills/.standardization/semantic-split/data/`（铁律4：产出物不嵌入技能目录） ## 工作流程 ### 语义拆分规则（摘要） > 详细规则见 `references/split_rules.md` **核心流程**：识别主语 → 划分块 → 提取目的/行为/动机 → 5W2H维度 + 约束强度标注 | 主语类型 | 块标记 | 块内元素 | |---------|--------|---------| | 用户（"我"） | `块1：用户` | 目的 / 行为(诉求) / 动机 | | AI助手（"你"） | `块2：执行者` | 同上 | | 第三方 | `块3：第三方-N` | 同上 | **边界情况速查**： | 关键情况 | 处理 | |---------|------| | 约束强度冲突 | 按最高强度处理（🔴>🟡🔴>🟡>⚪） | | 举例内容干扰 | 「比如/例如」后内容 → [EXAMPLE]，不作为核心约束 | | json 库为空 | 跳过①②，直接进入③模型思考 | ### 完整执行流程 **步骤 1-2**：接收输入 → 识别主语 & 划分块 接收用户原文 → 扫描识别主语代词（我/你/他/她/它/名称），每个独立主语 = 一个块 **步骤 2.5**：任务类型识别与 5W2H 初始化 > 内部执行，不输出。首次执行时读取 `references/task_type_defaults.md` + `references/constraint_annotation.md` 1. **任务类型识别**：制作PPT / 填写周报 / 安排行程 / 写邮件 / 策划活动 / 其他 2. **5W2H 维度初始化**：按任务类型从默认映射表填入默认值 3. **约束强度预标注**：🔴硬约束 / 🟡软约束 / ⚪无约束 **步骤 3**：提取块内元素（增强版） **注意力锚定**（内部执行，不输出，详见 `references/constraint_annotation.md` 第三节）： 1. `[CRITICAL]` — 硬约束，后续不可违反 2. `[CORE]` — 核心目标（动词+宾语） 3. `[ENTITY]` — 数字、时间、人名 4. `[EXAMPLE]` — 举例内容，降权不作为约束 5. `[RESISTANCE]` — 「但是/担心/难」后内容 6. 核心句重构：「[主语] 要 [CORE] 于 [时间/场景]」（≤20字） 逐句提取目的/行为/动机 + 5W2H维度 + 约束强度（详见 `references/split_rules.md` 第五节） **步骤 4**：结构化输出（增强版） ``` 【拆分结果】 ## 块 N：[主语名称] 角色：[用户/执行者/第三方] 目的：[核心目标] 诉求： 1. [核心交付物] 🔴 2. [支撑信息] 🟡 3. [附加要求] ⚪ 动机：[背景/原因/情绪] 5W2H：Why/What/Who/Where/When/How/How much — [值] 🔴/🟡/⚪ 阻力：[描述]（如有） 📌 核心句：[主语] 要 [CORE] 于 [时间/场景] 【确认询问】拆分是否完整准确？ ``` **步骤 4.5**：自我反查（内部执行，不输出） > 展示前强制执行（详见 `references/constraint_annotation.md` 第三节）： | 反查 | 检查内容 | 修正 | |------|---------|------| | 1 | 硬约束遗漏：`[CRITICAL]` 是否全在结果中？ | 补充 | | 2 | 约束误判：🟡 词被标为 🔴？ | 修正 | | 2b | 隐式升级：🟡 约束属组织规范/法律/安全？→ 🟡🔴 或 🔴 | 升级 | | 3 | 举例干扰：`[EXAMPLE]` 被当核心诉求？ | 降级 | | 4 | 5W2H 缺失：有明显可推断维度？ | 补充 `[推断]` | **步骤 5**：用户确认 - 如有遗漏 → 用户补充 → 更新结构 - 如全部正确 → 进入步骤 6 **步骤 6**：渐进加载与规划生成（增强版） > 加载：`references/loading_decision_tree.md`（必须）+ `references/planning_rules.md` + `references/constraint_annotation.md` + `references/json_schema.md`（按需） 按决策树执行： 1. 扫描规则级 json → 命中则加载并展示 2. 不命中则扫描能力级 json → 命中则加载并展示 3. 均不命中则**模型思考**（需加载 `planning_rules.md`） 4. 展示规划 → 询问用户是否执行 **【模型思考：双视角推理→整合】**（详见 `references/planning_rules.md` 第六节，不输出双方案） a) **聚焦方案**（内部）：5W2H取最窄值；守🔴硬约束；已验证方法；步骤≤30min b) **发散方案**（内部）：5W2H取最宽值；🔴可轻微突破（标注风险）；引入非惯用工具 c) **整合**（输出）：聚焦为骨架 + 发散创新点→🌟增强步骤 → **单一执行步骤** + 工作包分解 展示给用户的规划格式（详细规则见 `references/planning_rules.md` 第六节）： ``` 📌 任务：[名称] ｜🔴 硬约束：[列表] ｜🟡 软约束：[列表] 执行步骤： 步骤 N: [名称] ── serial ── milestone: ✅/❌ action: [操作] | depends_on: [依赖] | constraint_level: 🔴/🟡/⚪ 步骤 N🌟: [名称]（增强：来自发散方案） ⚠️ 风险：[说明]（如涉及🔴突破） 工作包：WP1: [描述](耗时, 前置) → 📍 检查点：[里程碑] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 来源：[规则级json / 能力级json / 模型思考（双视角整合）] ``` **步骤 7**：执行与 json 生成 - 用户确认执行 → 执行任务 - 分支③（不命中+确认执行）→ 完成后生成通用化能力级 json（加载 `json_schema.md`） - 其他分支 → 不生成新 json（除非用户主动要求） ## 注意事项 1. **双方案是内部推理，不输出给用户**：聚焦+发散仅在模型内部执行，最终整合为单一执行步骤 2. **约束强度不能只看关键词**：需上下文推断（如"尽量用公司模板"属组织规范，应升级为🟡🔴） 3. **注意力锚定在步骤3前强制执行**：[CRITICAL]/[CORE]/[ENTITY]/[EXAMPLE]/[RESISTANCE] 标记不可跳过 4. **自我反查在展示前强制执行**：4项检查+反查2b（隐式约束升级），全部通过才进入用户确认 ## 脚本工具 `json_manager.py` — 管理能力级/规则级 json 的 CLI 工具（零外部依赖） | 子命令 | 功能 | |--------|------| | `scan` / `categorize` | 按关键词扫描 / 按 tags 归类统计 | | `create` / `validate` | 创建 json 骨架 / 验证格式 | | `generalize` / `rule-gen` | 字段通用化 / 从能力级生成规则级 | | `list` / `info` | 列出所有 json / 显示详情 | ## 参考文档（渐进加载） | 文件 | 加载时机 | |------|---------| | `split_rules.md` | 步骤 2、3 首次 | | `loading_decision_tree.md` | 步骤 6 **必须** | | `planning_rules.md` | 模型思考时 | | `json_schema.md` | 生成 json 时 | | `constraint_annotation.md` | 步骤 2.5 / 3 / 6 | | `task_type_defaults.md` | 步骤 2.5 首次 | | `examples.md` | 参考格式时 | **v2.5.0** — 5W2H维度提取 · 约束强度标注(🔴🟡⚪) · 注意力锚定 · 双视角推理整合 · 工作包分解

path: _meta.json
content: {
  "name": "semantic-split",
  "version": "2.5.0",
  "description": "语义拆分与智能规划技能。将自然语言拆分为结构化需求块，基于5W2H维度提取与约束标注增强语义理解，双视角推理整合为单一执行步骤，支持自增强json沉淀机制。",
  "author": "wUwproject",
  "tags": [
    "语义拆分",
    "任务规划",
    "json沉淀",
    "渐进加载",
    "5W2H",
    "约束标注"
  ],
  "data_dir": ".standardization/semantic-split/data/"
}


path: scripts/json_manager.py
content: #!/usr/bin/env python3
"""
semantic-split JSON Manager v1.0

统一管理能力级/规则级 json 的 CLI 工具。
零外部依赖，仅使用 Python 标准库。
产出物遵循铁律4：数据统一存放于 ~/standardization/semantic-split/data/。

用法:
  python json_manager.py <subcommand> [options]

Subcommands:
  scan       扫描 json 库，按关键词匹配返回结果
  categorize 归类统计所有能力级 json，判断是否达到规则级阈值
  generalize 将具体内容通用化为占位符（字段替换）
  rule-gen   根据多个同类能力级 json 生成规则级 json 框架
  list       列出所有 json 文件（支持过滤）
  create     创建新的能力级/规则级 json 文件
  validate   验证 json 文件格式正确性
  info       显示 json 文件详情
"""

import json
import os
import sys
import argparse
from pathlib import Path
from collections import Counter
from datetime import datetime, date
from copy import deepcopy

# ============================================================
# 路径常量（铁律4：产出物存至 skills/.standardization/semantic-split/data/）
# ============================================================

SKILL_DIR = Path(__file__).resolve().parent.parent
DATA_DIR = SKILL_DIR.parent / ".standardization" / "semantic-split" / "data"
CAP_DIR = DATA_DIR / "capabilities"
RULE_DIR = DATA_DIR / "rules"

# ============================================================
# 工具函数
# ============================================================


def _load_json(filepath: Path) -> dict:
    """加载 json 文件"""
    with open(filepath, "r", encoding="utf-8") as f:
        return json.load(f)


def _save_json(filepath: Path, data: dict, indent: int = 2):
    """保存 json 文件"""
    filepath.parent.mkdir(parents=True, exist_ok=True)
    with open(filepath, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=indent)


def _iter_capabilities() -> list[tuple[Path, dict]]:
    """遍历所有能力级 json"""
    results = []
    if CAP_DIR.exists():
        for f in sorted(CAP_DIR.glob("*.json")):
            try:
                results.append((f, _load_json(f)))
            except (json.JSONDecodeError, Exception) as e:
                print(f"[WARN] 跳过损坏文件: {f.name} ({e})", file=sys.stderr)
    return results


def _iter_rules() -> list[tuple[Path, dict]]:
    """遍历所有规则级 json"""
    results = []
    if RULE_DIR.exists():
        for f in sorted(RULE_DIR.glob("*.json")):
            try:
                results.append((f, _load_json(f)))
            except (json.JSONDecodeError, Exception) as e:
                print(f"[WARN] 跳过损坏文件: {f.name} ({e})", file=sys.stderr)
    return results


def _match_score(keywords: list[str], json_data: dict) -> float:
    """
    计算关键词与 json 的匹配分数 (0.0 ~ 1.0)

    匹配维度：
    - tags 完全匹配：每个命中的 tag +0.15
    - name 包含关键词：每个命中 +0.2
    - description 包含关键词：每个命中 +0.1
    - steps.name/action 包含关键词：每个命中 +0.05
    """
    if not keywords:
        return 0.0

    score = 0.0
    kw_lower = [k.lower() for k in keywords]

    # tags 匹配
    tags = [t.lower() for t in json_data.get("tags", [])]
    for kw in kw_lower:
        for tag in tags:
            if kw in tag or tag in kw:
                score += 0.15
                break

    # name 匹配
    name = json_data.get("name", "").lower()
    for kw in kw_lower:
        if kw in name:
            score += 0.2

    # description 匹配
    desc = json_data.get("description", "").lower()
    for kw in kw_lower:
        if kw in desc:
            score += 0.1

    # steps 匹配
    for step in json_data.get("steps", []):
        step_text = f"{step.get('name', '')} {step.get('action', '')}".lower()
        for kw in kw_lower:
            if kw in step_text:
                score += 0.05
                break  # 每个步骤最多匹配一次

    return min(score, 1.0)


# ============================================================
# Subcommand: scan
# ============================================================


def cmd_scan(args):
    """
    扫描 json 库，按关键词匹配返回结果。

    搜索顺序：规则级 → 能力级（与决策树一致）
    """
    keywords = args.keywords
    threshold = args.threshold
    top_n = args.top
    json_type = args.type  # "all", "rule", "capability"

    if not keywords:
        print("[ERROR] 请提供至少一个关键词: --keywords kw1 kw2 ...")
        sys.exit(1)

    results = []

    # 扫描规则级
    if json_type in ("all", "rule"):
        for path, data in _iter_rules():
            s = _match_score(keywords, data)
            if s >= threshold:
                results.append((s, "rule", path, data))

    # 扫描能力级
    if json_type in ("all", "capability"):
        for path, data in _iter_capabilities():
            s = _match_score(keywords, data)
            if s >= threshold:
                results.append((s, "capability", path, data))

    # 按分数排序
    results.sort(key=lambda x: x[0], reverse=True)

    # 取 top N
    results = results[:top_n] if top_n > 0 else results

    # 输出
    if not results:
        print(json.dumps({
            "matched": False,
            "message": "未找到匹配的 json",
            "keywords": keywords,
            "threshold": threshold
        }, ensure_ascii=False, indent=2))
        return

    output = {
        "matched": True,
        "keywords": keywords,
        "total": len(results),
        "results": []
    }

    for score, jtype, path, data in results:
        entry = {
            "score": round(score, 3),
            "type": jtype,
            "id": data.get("id", path.stem),
            "name": data.get("name", ""),
            "file": str(path.relative_to(SKILL_DIR)),
            "steps_count": len(data.get("steps", [])) if jtype == "capability" else len(data.get("condensed_steps", []))
        }
        if jtype == "capability":
            entry["tags"] = data.get("tags", [])
            entry["generic_params"] = data.get("generic_params", [])
        elif jtype == "rule":
            entry["tags"] = data.get("tags", [])
            entry["capability_refs"] = [r.get("id", "") for r in data.get("capability_refs", [])]
        output["results"].append(entry)

    print(json.dumps(output, ensure_ascii=False, indent=2))


# ============================================================
# Subcommand: categorize
# ============================================================


def cmd_categorize(args):
    """
    归类统计所有能力级 json，按 tags 分组。
    判断哪些分组已达到规则级凝练阈值（≥5份）。
    """
    threshold = args.threshold

    # 收集所有能力级 json 的 tags
    tag_items = {}  # tag -> [(path, data), ...]
    all_caps = _iter_capabilities()

    for path, data in all_caps:
        for tag in data.get("tags", []):
            if tag not in tag_items:
                tag_items[tag] = []
            tag_items[tag].append((path, data))

    # 输出
    output = {
        "total_capabilities": len(all_caps),
        "threshold": threshold,
        "categories": {},
        "ready_for_rule": []
    }

    for tag in sorted(tag_items.keys()):
        items = tag_items[tag]
        ids = [d.get("id", p.stem) for p, d in items]
        count = len(items)
        ready = count >= threshold

        cat_entry = {
            "tag": tag,
            "count": count,
            "ready_for_rule": ready,
            "capability_ids": ids
        }
        output["categories"][tag] = cat_entry

        if ready:
            output["ready_for_rule"].append({
                "tag": tag,
                "count": count,
                "capability_ids": ids
            })

    print(json.dumps(output, ensure_ascii=False, indent=2))


# ============================================================
# Subcommand: generalize
# ============================================================


def cmd_generalize(args):
    """
    将具体内容通用化为占位符（字段替换）。

    支持两种模式：
    1. --params 模式：直接指定替换映射（推荐 AI 调用时使用）
    2. --auto 模式：自动检测中括号内容作为占位符（不替换，仅提取）

    输入：一个能力级 json 文件路径
    输出：通用化后的 json（写入新文件或 stdout）
    """
    input_file = Path(args.input)
    params = args.params  # ["钛合金马扎=[产品名称]", "明天=[截止时间]"]
    auto = args.auto
    output_file = args.output

    if not input_file.exists():
        print(f"[ERROR] 文件不存在: {input_file}", file=sys.stderr)
        sys.exit(1)

    data = _load_json(input_file)
    generic_params = list(data.get("generic_params", []))

    if params:
        # 构建替换映射
        replace_map = {}
        new_generic_params = []
        for p in params:
            if "=" not in p:
                print(f"[WARN] 忽略格式错误的参数: {p} (需要 key=value)", file=sys.stderr)
                continue
            original, placeholder = p.split("=", 1)
            replace_map[original] = placeholder
            if placeholder not in generic_params:
                new_generic_params.append(placeholder)
                generic_params.append(placeholder)

        # 执行替换（遍历所有字符串字段）
        data = _replace_in_dict(data, replace_map)

    if auto:
        # 自动模式：仅收集步骤 action 中已有的中括号占位符，不额外提取
        for step in data.get("steps", []):
            import re
            found = re.findall(r'\[([^\]]+)\]', step.get("action", ""))
            for p in found:
                placeholder = f"[{p}]"
                if placeholder not in generic_params:
                    generic_params.append(placeholder)
        data["generic_params"] = generic_params
    else:
        data["generic_params"] = generic_params

    # 更新元数据
    if auto or params:
        data["_generalized"] = True
        data["_generalized_at"] = str(date.today())

    # 输出
    if output_file:
        out_path = Path(output_file)
        _save_json(out_path, data)
        print(json.dumps({
            "status": "ok",
            "output_file": str(out_path.relative_to(SKILL_DIR)),
            "generic_params": data.get("generic_params", [])
        }, ensure_ascii=False, indent=2))
    else:
        print(json.dumps(data, ensure_ascii=False, indent=2))


def _replace_in_dict(obj, replace_map: dict):
    """递归替换字典中所有字符串字段的值"""
    if isinstance(obj, str):
        for original, placeholder in replace_map.items():
            obj = obj.replace(original, placeholder)
        return obj
    elif isinstance(obj, dict):
        return {k: _replace_in_dict(v, replace_map) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [_replace_in_dict(item, replace_map) for item in obj]
    return obj


def _auto_detect_params(data: dict) -> list[str]:
    """自动检测 json 中已有的占位符（中括号内容）"""
    params = []
    _extract_brackets(data, params)
    # 去重保序
    seen = set()
    result = []
    for p in params:
        if p not in seen:
            seen.add(p)
            result.append(p)
    return result


def _extract_brackets(obj, params: list):
    """递归提取所有中括号内容"""
    if isinstance(obj, str):
        import re
        found = re.findall(r'\[([^\]]+)\]', obj)
        params.extend(found)
    elif isinstance(obj, dict):
        for v in obj.values():
            _extract_brackets(v, params)
    elif isinstance(obj, list):
        for item in obj:
            _extract_brackets(item, params)


# ============================================================
# Subcommand: rule-gen
# ============================================================


def cmd_rule_gen(args):
    """
    根据多个同类能力级 json 生成规则级 json 框架。

    输入：多个能力级 json 文件路径（或 --tag 按标签自动选取）
    输出：规则级 json（打印到 stdout 或写入文件）
    """
    input_files = [Path(f) for f in args.files] if args.files else []
    tag = args.tag
    output_file = args.output

    # 获取能力级 json 列表
    caps = []
    if tag:
        for path, data in _iter_capabilities():
            if tag in data.get("tags", []):
                caps.append((path, data))
    elif input_files:
        for f in input_files:
            if not f.exists():
                print(f"[ERROR] 文件不存在: {f}", file=sys.stderr)
                sys.exit(1)
            caps.append((f, _load_json(f)))
    else:
        print("[ERROR] 请提供 --files 或 --tag", file=sys.stderr)
        sys.exit(1)

    if len(caps) < 2:
        print(f"[ERROR] 至少需要 2 个能力级 json，当前: {len(caps)}", file=sys.stderr)
        sys.exit(1)

    # 生成规则级 json
    rule = _generate_rule(caps, tag)

    # 输出
    if output_file:
        out_path = Path(output_file)
        if not out_path.suffix:
            out_path = out_path.with_suffix(".json")
        _save_json(RULE_DIR / out_path.name if not out_path.is_absolute() else out_path, rule)
        print(json.dumps({
            "status": "ok",
            "output_file": out_path.name,
            "source_count": len(caps),
            "condensed_steps_count": len(rule["condensed_steps"]),
            "capability_refs": [r["id"] for r in rule["capability_refs"]]
        }, ensure_ascii=False, indent=2))
    else:
        print(json.dumps(rule, ensure_ascii=False, indent=2))


def _generate_rule(caps: list[tuple[Path, dict]], tag: str = None) -> dict:
    """从多个能力级 json 生成规则级 json"""
    # 收集所有步骤
    all_steps = []
    cap_refs = []
    common_tags = Counter()

    for path, data in caps:
        cap_refs.append({
            "id": data.get("id", path.stem),
            "name": data.get("name", ""),
            "steps_range": f"s1-s{len(data.get('steps', []))}"
        })
        for t in data.get("tags", []):
            common_tags[t] += 1
        for step in data.get("steps", []):
            all_steps.append({
                "capability_id": data.get("id", path.stem),
                "step": step
            })

    # 提取公共步骤模式（按 name 相似度聚合）
    condensed = _condense_steps(all_steps, cap_refs)

    # 确定规则名称
    if tag:
        rule_name = f"{tag}类任务规则"
        rule_id = f"rule_{tag}_v1"
    else:
        # 从 tags 中取出现频率最高的
        top_tag = common_tags.most_common(1)[0][0] if common_tags else "general"
        rule_name = f"{top_tag}类任务规则"
        rule_id = f"rule_{top_tag}_v1"

    # 确定最佳 load_capability 映射
    for cs in condensed:
        if not cs.get("load_capability_if_detail_needed"):
            # 默认映射到第一个包含该步骤的能力级
            for ref in cap_refs:
                cs["load_capability_if_detail_needed"] = ref["id"]
                break

    rule = {
        "id": rule_id,
        "type": "rule",
        "name": rule_name,
        "version": "1.0.0",
        "created_at": str(date.today()),
        "description": f"统合 {len(caps)} 个能力级 json 提炼生成的规则",
        "source_capability_count": len(caps),
        "capability_refs": cap_refs,
        "condensed_steps": condensed,
        "tags": [t for t, c in common_tags.most_common(3) if c >= len(caps) // 2]
    }

    return rule


def _condense_steps(all_steps: list[dict], cap_refs: list[dict]) -> list[dict]:
    """
    将多个能力级的步骤压缩为规则级 condensed_steps。

    策略：
    1. 按 step.name 聚类（相似度匹配）
    2. 每个聚类生成一个 condensed_step
    3. 保留 maps_to 映射
    """
    groups = []
    used = set()

    for i, entry_i in enumerate(all_steps):
        if i in used:
            continue

        step_i = entry_i["step"]
        group = [entry_i]
        used.add(i)

        for j, entry_j in enumerate(all_steps):
            if j in used:
                continue

            step_j = entry_j["step"]
            if _steps_similar(step_i, step_j):
                group.append(entry_j)
                used.add(j)

        groups.append(group)

    # 生成 condensed_steps
    condensed = []
    for idx, group in enumerate(groups, 1):
        representative = group[0]["step"]
        maps_to = [f"{e['capability_id']}.{e['step']['id']}" for e in group]

        # 并行组：如果组内任何步骤有并行组，保留
        pg = None
        for e in group:
            if e["step"].get("parallel_group"):
                pg = f"r{idx}"
                break

        # milestone：如果组内所有步骤都是 milestone
        ms = all(e["step"].get("milestone", False) for e in group)

        cs = {
            "id": f"r{idx}",
            "name": representative.get("name", f"步骤{idx}"),
            "milestone": ms,
            "parallel_group": pg,
            "maps_to": maps_to,
            "load_capability_if_detail_needed": group[0]["capability_id"]
        }
        condensed.append(cs)

    return condensed


def _steps_similar(step_a: dict, step_b: dict) -> bool:
    """判断两个步骤是否相似（用于聚类）"""
    name_a = step_a.get("name", "").lower()
    name_b = step_b.get("name", "").lower()

    # 完全相同
    if name_a == name_b:
        return True

    # 包含关系
    if name_a in name_b or name_b in name_a:
        return True

    # 核心词重叠（去停用词后）
    stopwords = {"的", "与", "和", "及", "或", "等", "进行", "完成", "执行"}
    words_a = set(name_a) - stopwords
    words_b = set(name_b) - stopwords

    if not words_a or not words_b:
        return False

    overlap = len(words_a & words_b) / max(len(words_a), len(words_b))
    return overlap >= 0.6


# ============================================================
# Subcommand: list
# ============================================================


def cmd_list(args):
    """列出所有 json 文件"""
    json_type = args.type
    verbose = args.verbose
    tag_filter = args.tag

    results = []

    if json_type in ("all", "rule"):
        for path, data in _iter_rules():
            if tag_filter and tag_filter not in data.get("tags", []):
                continue
            entry = {
                "type": "rule",
                "id": data.get("id", path.stem),
                "name": data.get("name", ""),
                "version": data.get("version", "?"),
                "file": path.name,
                "tags": data.get("tags", [])
            }
            if verbose:
                entry["capability_refs"] = [r.get("id", "") for r in data.get("capability_refs", [])]
                entry["condensed_steps_count"] = len(data.get("condensed_steps", []))
            results.append(entry)

    if json_type in ("all", "capability"):
        for path, data in _iter_capabilities():
            if tag_filter and tag_filter not in data.get("tags", []):
                continue
            entry = {
                "type": "capability",
                "id": data.get("id", path.stem),
                "name": data.get("name", ""),
                "version": data.get("version", "?"),
                "file": path.name,
                "tags": data.get("tags", [])
            }
            if verbose:
                entry["steps_count"] = len(data.get("steps", []))
                entry["generic_params"] = data.get("generic_params", [])
                entry["milestones"] = [s["id"] for s in data.get("steps", []) if s.get("milestone")]
            results.append(entry)

    output = {
        "total": len(results),
        "filter": {"type": json_type, "tag": tag_filter},
        "items": results
    }

    print(json.dumps(output, ensure_ascii=False, indent=2))


# ============================================================
# Subcommand: create
# ============================================================


def cmd_create(args):
    """创建新的能力级/规则级 json 骨架文件"""
    json_type = args.type
    name = args.name
    output = args.output

    if not name:
        print("[ERROR] 请提供 --name", file=sys.stderr)
        sys.exit(1)

    if json_type == "capability":
        data = {
            "id": name,
            "type": "capability",
            "name": name,
            "version": "1.0.0",
            "created_at": str(date.today()),
            "description": "",
            "generic_params": [],
            "steps": [],
            "tags": []
        }
        default_dir = CAP_DIR
        default_file = f"{name}.json"
    elif json_type == "rule":
        data = {
            "id": name,
            "type": "rule",
            "name": name,
            "version": "1.0.0",
            "created_at": str(date.today()),
            "description": "",
            "source_capability_count": 0,
            "capability_refs": [],
            "condensed_steps": [],
            "tags": []
        }
        default_dir = RULE_DIR
        default_file = f"{name}.json"
    else:
        print(f"[ERROR] 未知类型: {json_type}，请使用 capability 或 rule", file=sys.stderr)
        sys.exit(1)

    out_path = Path(output) if output else default_dir / default_file
    _save_json(out_path, data)

    print(json.dumps({
        "status": "ok",
        "type": json_type,
        "file": str(out_path.relative_to(SKILL_DIR)),
        "message": f"骨架文件已创建，请编辑填充内容"
    }, ensure_ascii=False, indent=2))


# ============================================================
# Subcommand: validate
# ============================================================


def cmd_validate(args):
    """验证 json 文件格式正确性"""
    filepath = Path(args.file)

    if not filepath.exists():
        print(f"[ERROR] 文件不存在: {filepath}", file=sys.stderr)
        sys.exit(1)

    errors = []
    warnings = []

    try:
        data = _load_json(filepath)
    except json.JSONDecodeError as e:
        print(json.dumps({
            "valid": False,
            "file": filepath.name,
            "errors": [f"JSON 解析失败: {e}"]
        }, ensure_ascii=False, indent=2))
        return

    json_type = data.get("type", "unknown")

    # 通用必填字段
    required_common = ["id", "type", "name", "version", "created_at", "description", "tags"]
    for field in required_common:
        if field not in data:
            errors.append(f"缺少必填字段: {field}")

    if json_type == "capability":
        cap_required = ["generic_params", "steps"]
        for field in cap_required:
            if field not in data:
                errors.append(f"缺少能力级必填字段: {field}")

        # 验证步骤
        if "steps" in data:
            step_required = ["id", "name", "action", "parallel_group", "milestone", "dependency_heat", "depends_on"]
            for i, step in enumerate(data["steps"]):
                for sf in step_required:
                    if sf not in step:
                        errors.append(f"步骤 {i} ({step.get('id', '?')}) 缺少字段: {sf}")

                # 验证 depends_on 引用
                all_step_ids = {s.get("id") for s in data["steps"]}
                for dep in step.get("depends_on", []):
                    if dep not in all_step_ids:
                        errors.append(f"步骤 {step.get('id')} 的 depends_on 引用不存在: {dep}")

                # 验证 dependency_heat 范围
                dh = step.get("dependency_heat", -1)
                if not isinstance(dh, (int, float)) or dh < 0 or dh > 10:
                    warnings.append(f"步骤 {step.get('id')} dependency_heat={dh} 不在 0-10 范围内")

            # 验证 parallel_group 引用一致性
            pg_members = {}
            for step in data["steps"]:
                pg = step.get("parallel_group")
                if pg:
                    if pg not in pg_members:
                        pg_members[pg] = []
                    pg_members[pg].append(step.get("id"))

            for pg, members in pg_members.items():
                if len(members) < 2:
                    warnings.append(f"并行组 '{pg}' 仅含 {len(members)} 个步骤（至少需要2个）")

    elif json_type == "rule":
        rule_required = ["source_capability_count", "capability_refs", "condensed_steps"]
        for field in rule_required:
            if field not in data:
                errors.append(f"缺少规则级必填字段: {field}")

        # 验证 condensed_steps
        if "condensed_steps" in data:
            cs_required = ["id", "name", "milestone", "parallel_group", "maps_to", "load_capability_if_detail_needed"]
            for i, cs in enumerate(data["condensed_steps"]):
                for sf in cs_required:
                    if sf not in cs:
                        errors.append(f"condensed_step {i} ({cs.get('id', '?')}) 缺少字段: {sf}")

    else:
        warnings.append(f"未知类型: {json_type}，应为 'capability' 或 'rule'")

    # 检查 generic_params 是否在内容中被引用
    if json_type == "capability" and "generic_params" in data and "steps" in data:
        content_str = json.dumps(data["steps"], ensure_ascii=False)
        for param in data["generic_params"]:
            if param not in content_str:
                warnings.append(f"generic_params 中的 '{param}' 未在步骤内容中被引用")

    output = {
        "valid": len(errors) == 0,
        "file": filepath.name,
        "type": json_type,
        "errors": errors,
        "warnings": warnings,
        "summary": {
            "steps": len(data.get("steps", data.get("condensed_steps", []))),
            "tags": len(data.get("tags", [])),
            "errors_count": len(errors),
            "warnings_count": len(warnings)
        }
    }

    print(json.dumps(output, ensure_ascii=False, indent=2))


# ============================================================
# Subcommand: info
# ============================================================


def cmd_info(args):
    """显示 json 文件详情"""
    filepath = Path(args.file)

    if not filepath.exists():
        print(f"[ERROR] 文件不存在: {filepath}", file=sys.stderr)
        sys.exit(1)

    data = _load_json(filepath)
    data["_file"] = str(filepath.relative_to(SKILL_DIR))
    data["_file_size"] = filepath.stat().st_size

    print(json.dumps(data, ensure_ascii=False, indent=2))


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


def main():
    parser = argparse.ArgumentParser(
        prog="json_manager",
        description="semantic-split JSON 管理工具 v1.0"
    )
    subparsers = parser.add_subparsers(dest="command", help="可用子命令")

    # --- scan ---
    p_scan = subparsers.add_parser("scan", help="扫描 json 库，按关键词匹配")
    p_scan.add_argument("--keywords", nargs="+", required=True, help="搜索关键词")
    p_scan.add_argument("--threshold", type=float, default=0.1, help="最低匹配分数 (默认 0.1)")
    p_scan.add_argument("--top", type=int, default=5, help="返回前 N 个结果 (0=全部, 默认 5)")
    p_scan.add_argument("--type", choices=["all", "rule", "capability"], default="all", help="搜索范围")

    # --- categorize ---
    p_cat = subparsers.add_parser("categorize", help="归类统计能力级 json")
    p_cat.add_argument("--threshold", type=int, default=5, help="规则级凝练阈值 (默认 5)")

    # --- generalize ---
    p_gen = subparsers.add_parser("generalize", help="通用化（字段替换为占位符）")
    p_gen.add_argument("--input", required=True, help="输入的 json 文件路径")
    p_gen.add_argument("--params", nargs="*", help='替换映射: "原文=占位符" ...')
    p_gen.add_argument("--auto", action="store_true", help="自动检测占位符（仅提取，不替换）")
    p_gen.add_argument("--output", help="输出文件路径（不指定则输出到 stdout）")

    # --- rule-gen ---
    p_rule = subparsers.add_parser("rule-gen", help="生成规则级 json 框架")
    p_rule.add_argument("--files", nargs="*", help="输入的能力级 json 文件路径")
    p_rule.add_argument("--tag", help="按标签自动选取能力级 json")
    p_rule.add_argument("--output", help="输出文件路径（不指定则输出到 stdout）")

    # --- list ---
    p_list = subparsers.add_parser("list", help="列出所有 json 文件")
    p_list.add_argument("--type", choices=["all", "rule", "capability"], default="all", help="文件类型")
    p_list.add_argument("--tag", help="按标签过滤")
    p_list.add_argument("--verbose", "-v", action="store_true", help="显示详细信息")

    # --- create ---
    p_create = subparsers.add_parser("create", help="创建新 json 骨架文件")
    p_create.add_argument("--type", choices=["capability", "rule"], required=True, help="json 类型")
    p_create.add_argument("--name", required=True, help="json id / 名称")
    p_create.add_argument("--output", help="输出路径（不指定则使用默认目录）")

    # --- validate ---
    p_val = subparsers.add_parser("validate", help="验证 json 文件格式")
    p_val.add_argument("--file", required=True, help="要验证的 json 文件路径")

    # --- info ---
    p_info = subparsers.add_parser("info", help="显示 json 文件详情")
    p_info.add_argument("--file", required=True, help="json 文件路径")

    args = parser.parse_args()

    if not args.command:
        parser.print_help()
        sys.exit(0)

    # 路由到对应子命令
    cmd_map = {
        "scan": cmd_scan,
        "categorize": cmd_categorize,
        "generalize": cmd_generalize,
        "rule-gen": cmd_rule_gen,
        "list": cmd_list,
        "create": cmd_create,
        "validate": cmd_validate,
        "info": cmd_info,
    }

    cmd_map[args.command](args)


if __name__ == "__main__":
    main()


path: references/automation_tasks.md
content: # 定时/自动化任务

> **加载时机**：用户要求设置定时任务或自动化任务时加载

---

## 一、轻量级任务

**目标**：将已积累的能力级 json 进行归类，提炼思考链，形成规则级 json。

**触发方式**：定时（如每周日）或用户主动要求

**执行逻辑**：
1. 扫描 `skills/.standardization/semantic-split/data/capabilities/` 目录下所有能力级 json
2. 按 `tags` 字段归类，统计每类数量
3. 对数量 ≥ 5 的类别，提炼思考链（合并相似步骤、抽象共同模式）
4. 生成规则级 json，内嵌 `capability_refs` 引用所有来源能力级
5. 保存至 `skills/.standardization/semantic-split/data/rules/` 目录

**注意**：规则级 json 的结构规范见 `json_schema.md`。

---

## 二、重量级任务

**目标**：根据近期记忆中的任务，批量输出通用化能力级 json。

**触发方式**：定时（如每天/每周）或用户主动要求

**执行逻辑**：
1. 读取近期记忆文件（memory/ 目录下近 N 天的日志）
2. 识别其中有价值的任务执行记录
3. 对每条记录，提取步骤链，执行通用化（字段替换）
4. 生成能力级 json 保存至 `skills/.standardization/semantic-split/data/capabilities/` 目录
5. 可生成多个 json（一个任务一个）
6. 可选：对归类后 ≥ 5 份的类别顺带生成规则级 json

**注意**：重量级任务消耗更多 token，建议在低峰时段执行。通用化规则见 `json_schema.md`。

---

## 三、JSON 存储结构

```
skills/.standardization/semantic-split/data/    ← 铁律4：产出物不嵌入技能目录
├── capabilities/                     # 能力级 json 存储目录
│   ├── make_product_ppt_v1.json
│   └── ...
└── rules/                            # 规则级 json 存储目录
    ├── rule_ppt_v1.json
    └── ...
```


path: references/changelog.md
content: # semantic-split 版本更新日志

---

## v2.5.0（2026-05-23）

**改写类型：标准化改造 — SKILL.md 结构规范化 + 示例更新 + 路径修正**

### 变更内容

#### SKILL.md 结构规范化
- 章节重排为规范模板顺序：触发场景→核心能力→快速开始→主要流程→注意事项→脚本工具→参考文档
- 去掉标题中的版本号 `(Semantic Split v2.4)`，版本号仅在 frontmatter
- 「第一/二/三部分」改为标准章节名（语义拆分规则摘要、完整执行流程、触发场景→注意事项）
- 新增「注意事项」章节：双方案是内部推理、约束强度需上下文推断、锚定/反查不可跳过
- 触发场景从末尾移至第二个章节（核心能力之后）

#### examples.md 更新
- 新增示例 1：v2.4+ 增强格式（含约束标注🔴🟡⚪、5W2H维度、核心句、自我反查、隐式约束升级🟡🔴、双视角整合规划输出）
- 保留示例 2：v2.3 基础格式作为对照

#### 路径修正
- `json_schema.md` 第四节目录树：修正为 `skills/.standardization/semantic-split/data/`（铁律4）
- `automation_tasks.md` 第三节目录树：同上修正
- `loading_decision_tree.md` 两处路径：同上修正
- `changelog.md` 三处历史路径记录：同上修正
- `SKILL.md` 知识库路径说明：同上修正

### 标准化审查结果
- ERROR=0, PASS=11, SKIP=1(R-10)
- SKILL.md 行数=200（符合≤200行规范）

---

## v2.4.1（2026-05-23）

**改写类型：标准化改造 — SKILL.md 瘦身 + 渐进式MD体系完善**

### 变更内容

#### SKILL.md 主文件瘦身（315行 → 200行）
- 第一部分「语义拆分规则」详细内容迁移至 `references/split_rules.md`，主文件仅保留摘要表格
- 步骤4输出模板压缩（5W2H逐行展开改为单行格式）
- 步骤6加载提示和双视角推理描述精简
- 步骤1-2合并
- 触发条件精简
- 脚本工具表合并
- 参考文档表精简

#### 新增文件
- `references/split_rules.md` — 从SKILL.md第一部分迁移的完整语义拆分规则（划分块、诉求聚合、主语映射表、边界情况、5W2H提取规则）

#### 格式统一
- references/ 内部交叉引用统一为不带 `references/` 前缀
- SKILL.md 内引用统一带 `references/` 前缀
- `automation_tasks.md` 2处引用修正
- `planning_rules.md` 1处引用修正
- 参考文档表增加 `split_rules.md` 条目

### 标准化审查结果
- ERROR=0, WARN=0, PASS=11, SKIP=1(R-10)
- SKILL.md 行数=200（符合≤200行规范）

---

## v2.4.0（2026-05-23）

**改写类型：功能增强 — 5W2H维度提取 + 约束标注 + 双视角推理整合**

### 变更内容

#### 新增功能
- **步骤 2.5：任务类型识别与 5W2H 初始化** — 自动判断任务类型，按映射表填入 5W2H 默认值，预标注约束强度
- **步骤 3 增强：注意力锚定 + 5W2H 提取 + 约束标注** — 提取前强制执行锚定（[CRITICAL]/[CORE]/[ENTITY]/[EXAMPLE]/[RESISTANCE]），逐句增加 5W2H 维度和约束强度标注
- **步骤 4 增强：结构化输出含约束标注** — 诉求点增加 🔴🟡⚪ 标记，新增 5W2H 维度输出、阻力记录、核心句
- **步骤 4.5：自我反查** — 输出前强制执行硬约束遗漏/约束误判/举例干扰/5W2H 完整性四项反查
- **步骤 6 增强：双视角推理整合** — 模型思考时从聚焦+发散两个视角推理，整合为单一执行步骤输出，🌟标记发散增强步骤
- **工作包分解** — 聚焦式 WP 格式 + 探索式模块格式

#### 新增文件
- `references/task_type_defaults.md` — 5 种任务类型（制作PPT/填写周报/安排行程/写邮件/策划活动）的 5W2H 默认值映射表 + 通用默认值
- `references/constraint_annotation.md` — 约束强度定义（🔴🟡⚪）、自动识别规则、注意力锚定规则、自我反查、双方案处理差异、整合时约束处理规则

#### 文件改动
- `SKILL.md` — 版本号 2.3.0→2.4.0，核心能力表扩展（8项），步骤 2.5/3/4/4.5/6 增强，参考文档表更新
- `references/planning_rules.md` — 末尾追加第六节（双视角推理与整合规则）+ 第七节（约束遵循检查）
- `references/json_schema.md` — steps 子字段表增加 `constraint_level`/`source` 可选字段，示例 json 增加 `s3c` 发散增强步骤
- `_meta.json` — 版本号 2.3.0→2.4.0，description 更新，tags 增加 5W2H/约束标注

#### 未改动文件
- `references/loading_decision_tree.md` — 渐进加载逻辑不变
- `references/automation_tasks.md` — 定时任务逻辑不变
- `references/examples.md` — 示例格式不变
- `scripts/json_manager.py` — 脚本逻辑不变

### 标准化审查结果
- ERROR=0, WARN=0, PASS=11, SKIP=1(R-10)

---

## v2.3.0（2026-05-23）

**改写类型：产出物路径修正**

- DATA_DIR 路径修正（Path.home()/standardization → SKILL_DIR.parent/.standardization/semantic-split/data/）
- _meta.json 补充 data_dir 字段

---

**改写类型：skill-standardization 标准化改造（R-11 产出物迁移 + 结构补全）**

### 变更内容

#### R-11 产出物路径修正（铁律4）
- `data/capabilities/make_product_ppt_v1.json` 从技能目录迁移至 `skills/.standardization/semantic-split/data/capabilities/`
- `scripts/json_manager.py` DATA_DIR 路径常量更新：`SKILL_DIR / "data"` → `Path.home() / ".workbuddy" / "semantic-split" / "data"`
- 旧 `data/` 目录已删除

#### 交叉引用修复（9处）
- `references/automation_tasks.md`：4 处 `data/` 路径 + 目录树更新
- `references/loading_decision_tree.md`：2 处路径引用更新
- `references/json_schema.md`：3 处 CLI 示例路径 + 目录树更新

#### 结构补全
- 新增「快速开始」章节（含 scan/categorize/create/generalize 四个核心命令示例）
- 知识库路径说明：`skills/.standardization/semantic-split/data/`

#### 版本号同步
- SKILL.md `version:` `2.1.0` → `2.2.0`
- `_meta.json` `"version"` `2.1.0` → `2.2.0`

### 标准化审查结果
- ERROR=0, WARN=1, PASS=5（预修复：1E → 0E）

---

## v2.1.0（2026-05-22）

**改写类型：初始标准化**

- 初始版本，由 skill-standardization 引擎创建


path: references/constraint_annotation.md
content: # 约束强度标注规则

> **加载时机**：步骤 2.5、步骤 3、步骤 6（模型思考）时加载

---

## 一、约束强度定义

| 强度 | 标记 | 关键词 | 处理规则 |
|------|------|--------|---------|
| 硬约束 | 🔴 | 必须、只能、截止、指定、强制、不允许、不得 | 聚焦方案严格遵守；发散方案可轻微突破但必须标注风险 |
| 软约束 | 🟡 | 最好、尽量、如果可能、建议、通常、希望 | 聚焦方案遵守；发散方案可尝试其他方法 |
| 无约束 | ⚪ | 未提及或使用随意、大概、大概就行 | 两个方案均可自由处理 |

---

## 二、约束强度自动识别规则

扫描用户任务文本，对每个 5W2H 维度独立判断：

1. 该维度的描述附近是否有 🔴 关键词？→ 🔴 硬约束
2. 否则，是否有 🟡 关键词？→ 🟡 软约束
3. 否则 → ⚪ 无约束

**就近原则**：约束关键词只修饰其直接关联的内容，不跨句传播。

**示例**：
- "本周五前**必须**提交PPT，**尽量**用公司模板"
  → When 维度：🔴 硬约束（"必须" + "本周五前"）
  → How 维度：🟡 软约束（"尽量" + "用公司模板"）
  → What 维度：⚪ 无约束（"PPT" 无约束词）

---

## 二-B、隐式约束升级规则

> ⚠️ 关键词初判只是第一步。很多约束的**真实强度**被用户的口头弱化表达掩盖了，需要通过上下文推断还原。

### 核心逻辑

```
关键词初判 → 上下文复核 → 可能升级 → 双标注输出
```

### 升级判断依据

初判为 🟡 的约束，检查其内容是否属于以下领域：

| 领域 | 典型场景 | 升级结果 | 理由 |
|------|---------|---------|------|
| **组织规范** | 公司模板、品牌色、审批流程、命名规范 | 🟡🔴 软表达+硬语义 | 组织规范名义上"建议"实则强制违反有后果 |
| **法律合规** | 合同条款、数据保护、财务审计 | 🔴 | 法律领域无"尽量"，应直接升级 |
| **安全底线** | 权限控制、加密要求、操作规程 | 🔴 | 安全无弹性 |
| **协作依赖** | 接口格式、交付物标准、会议时间 | 🟡＋"影响下游"标注 | 违反会影响他人，但不一定不可协商 |
| **个人偏好** | 颜色选择、工具选择、格式偏好 | 🟡（维持） | 纯个人偏好无需升级 |

### 双标注格式

升级后的约束使用**双标注**：`🟡🔴` — 软约束表达 + 硬约束语义

含义：
- 🟡（用户口头说的）：尽量、最好、建议...
- 🔴（上下文推断的）：实际上可能不可违反

### 处理规则

| 标注 | 聚焦方案 | 发散方案 |
|------|---------|---------|
| 🟡🔴 | **按🔴执行**（保守处理，假设不可违反） | 按🟡探索（可以尝试突破，但必须标注风险+提供备用方案） |
| 🟡＋影响下游 | 按🟡遵守，步骤中注明协作影响 | 可协商替代，但需列出受影响方 |
| 🟡（维持） | 按🟡遵守 | 可自由替代 |

### 示例

- "尽量用公司模板" → 初判🟡 → 上下文复核："公司模板"属于组织规范 → **升级为 🟡🔴**
  - 聚焦方案：严格遵守公司模板
  - 发散方案：🌟可尝试其他模板，但标注"风险：违反品牌规范"

- "最好用蓝色" → 初判🟡 → 上下文复核：纯个人偏好 → **维持🟡**
  - 聚焦方案：使用蓝色
  - 发散方案：可自由选色

- "尽量符合数据保护要求" → 初判🟡 → 上下文复核：法律合规 → **升级为🔴**
  - 两个方案都必须严格遵守

---

## 三、注意力锚定规则

> ⚠️ 在步骤 3（提取块内元素）之前，模型必须先执行以下内部锚定步骤。本步骤不向用户输出，但必须执行。

### 3.1 强制关注点提取

1. **硬约束标记**：扫描文本中的「必须、只能、截止、指定、强制、不允许、不得」，将其后内容标记为 `[CRITICAL]`，任何后续步骤不可违反
2. **核心目标提取**：识别主要任务动词（制作/安排/填写/规划/写）及其直接宾语，标记为 `[CORE]`
3. **实体提取**：提取所有数字、时间、人名/项目名称，标记为 `[ENTITY]`
4. **降权标记**：「比如/例如/像/假如」后面的内容，标记为 `[EXAMPLE]`，后续提取时权重降低，不作为约束
5. **阻力提取**：「但是/不过/担心/怕/难/卡」后面的内容，标记为 `[RESISTANCE]`，在诉求聚合时优先保留
6. **核心句重构**：用一句话（≤20字）重述任务，格式：「[主语] 要 [CORE] 于 [时间/场景]」

### 3.2 自我反查

拆分结果输出前，模型强制执行以下反查：

| 反查 | 检查内容 | 修正动作 |
|------|---------|---------|
| 反查 1 | 硬约束遗漏：所有 `[CRITICAL]` 内容是否体现在拆分结果中？ | 如否 → 补充遗漏 |
| 反查 2 | 约束强度误判：是否有将 🟡 软约束词误标为 🔴？ | 如是 → 修正为 🟡 |
| 反查 2b | 隐式约束升级：是否有 🟡 约束属于组织规范/法律合规/安全底线，应升级为 🟡🔴 或 🔴？ | 如是 → 按升级规则处理 |
| 反查 3 | 举例干扰：是否有 `[EXAMPLE]` 内容被当作核心诉求？ | 如是 → 降级为参考信息 |
| 反查 4 | 5W2H 完整性：各维度是否有明显可推断但缺失的？ | 如是 → 补充 `[推断]` 默认值 |

✅ 全部通过后才进入用户确认环节。

---

## 四、双方案对约束的处理差异

| 维度属性 | 聚焦方案 | 发散方案 |
|---------|---------|---------|
| 🔴 硬约束 | 严格遵守，不可违反 | 可轻微突破，但必须：1) 标注 🌟 风险警告 2) 提供备用方案 |
| 🟡🔴 软表达+硬语义 | 按🔴执行（假设不可违反） | 按🟡探索，但必须标注风险+提供备用方案 |
| 🟡 软约束 | 遵守（按默认处理） | 可尝试替代方法，注明"如果不用[软约束]会怎样" |
| ⚪ 无约束 | 采用最有效率的处理方式 | 可尝试非常规方式 |

---

## 五、整合时的约束处理规则

发散方案的创新点若涉及约束突破，整合时按约束类型区分处理：

**🔴 硬约束突破**：
- 该突破**风险可控** → 作为 🌟 增强步骤，附风险说明
- 该突破**风险高** → 仅标注为「可选尝试」，不嵌入主步骤

**🟡🔴 软表达+硬语义突破**：
- 整合时**默认按🔴处理**（聚焦方案骨架中不突破）
- 发散方案的创新点可保留为🌟步骤，但必须标注"⚠️ 风险：可能违反[组织规范/品牌要求等]，执行前需确认"
- 同时提供备用步骤（按🔴执行的方案）

---

## 六、约束清单输出格式

```
【约束清单】
🔴 硬约束（不可违反）：
  - When：本周五前必须提交
  - What：PPT格式

🟡🔴 软表达+硬语义（用户弱化表达，但上下文推断可能不可违反）：
  - How：使用公司模板（"尽量"，但涉及品牌规范）

🟡 软约束（尽量遵守）：
  - （本例无）

⚪ 无约束：
  - Why / Who / Where / How much：未指定
```


path: references/examples.md
content: # 拆分示例

> **加载时机**：需要参考格式时加载

---

## 示例 1：v2.4+ 增强格式（含约束标注、5W2H、核心句）

### 输入

> "这个PPT太难搞了，我想让你为我做个PPT，明天下午3点前必须交，尽量用公司模板，就介绍钛合金马扎产品，我们研发了200多天，开了200次产品会就为了精益求精，他主要成分就是钛合金，和常见的马扎功能一样，但是防水、耐磨、不易损坏，还很轻，你为我做PPT吧。"

### 注意力锚定（内部，不输出）

- `[CRITICAL]` 明天下午3点前必须交 → 🔴 硬约束
- `[CORE]` 做PPT → 核心目标
- `[ENTITY]` 钛合金马扎、200多天、200次、下午3点 → 实体
- `[EXAMPLE]` （无）
- `[RESISTANCE]` PPT太难搞了 → 阻力
- 核心句重构：「用户 要 做PPT 于 明天下午3点前」

### 隐式约束升级（内部，不输出）

- "尽量用公司模板" → 初判🟡 → 上下文复核：属组织规范 → **升级为 🟡🔴**

### 拆分结果

```
【拆分结果】

## 块 1：用户（"我"）
  角色：requester（需求方）
  目的：明天要介绍产品
  诉求：
    1. 做一个PPT 🔴
    2. 明天下午3点前必须交 🔴
    3. 用公司模板 🟡🔴
    4. 介绍钛合金马扎产品 ⚪
    5. 研发200多天、200次产品会 ⚪
    6. 精益求精 ⚪
    7. 成分：钛合金 ⚪
    8. 功能同马扎+防水+耐磨+不易损坏+轻 ⚪
  动机：PPT太难搞了 [情绪]
  5W2H：
    Why — 有效传达产品信息 ⚪
    What — PPT介绍钛合金马扎 🔴
    Who — 目标听众（未指定，[推断]决策者）⚪
    Where — 会议/线上（未指定，[推断]）⚪
    When — 明天下午3点前 🔴
    How — 用公司模板制作 🟡🔴
    How much — 未指定 ⚪
  阻力：PPT太难搞了
  📌 核心句：用户要介绍产品于明天下午3点前

【确认询问】拆分是否完整准确？
```

### 自我反查（内部，不输出）

| 反查 | 结果 |
|------|------|
| 1. 硬约束遗漏 | ✅ "必须交"已在 When 维度 |
| 2. 约束误判 | ✅ 无误判 |
| 2b. 隐式升级 | ✅ "公司模板"已升级为🟡🔴 |
| 3. 举例干扰 | ✅ 无举例内容 |
| 4. 5W2H缺失 | ✅ Who/Where已补充[推断] |

### 规划输出（模型思考：双视角整合）

```
📌 任务：制作钛合金马扎产品PPT ｜🔴 硬约束：明天下午3点前交 ｜🟡 软约束：用公司模板

执行步骤：
  步骤 1: 收集产品资料 ── serial ── milestone: ✅
    action: 搜索整理钛合金马扎资料和核心参数 | depends_on: 无 | constraint_level: ⚪
  步骤 2: 设计PPT大纲 ── serial ── milestone: ✅
    action: 根据资料设计结构章节 | depends_on: 步骤1 | constraint_level: ⚪
  步骤 3a: 制作内容页 ── parallel_group: pg1 ── milestone: ❌
    action: 填充正文幻灯片内容 | depends_on: 步骤2 | constraint_level: ⚪
  步骤 3b: 设计视觉风格 ── parallel_group: pg1 ── milestone: ❌
    action: 按公司模板确定配色字体 | depends_on: 步骤2 | constraint_level: 🟡🔴
  步骤 3c🌟: AI生成备选视觉方案（增强：来自发散方案）
    ⚠️ 风险：可能偏离公司模板品牌规范，执行前需确认
  步骤 4: 审核修改 ── serial ── milestone: ✅
    action: 检查内容准确性与模板合规 | depends_on: 步骤3a,3b | constraint_level: 🟡🔴
  步骤 5: 导出PPT ── serial ── milestone: ❌
    action: 导出并确认明天3点前可交 | depends_on: 步骤4 | constraint_level: 🔴

工作包：WP1: 资料收集+大纲(1h) → 📍 检查点：大纲确认
        WP2: 内容制作+视觉设计(2h, 前置:WP1) → 📍 检查点：初稿完成
        WP3: 审核+导出(0.5h, 前置:WP2) → 📍 检查点：明天3点前交付
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
来源：模型思考（双视角整合）
```

---

## 示例 2：v2.3 基础格式（无约束标注）

### 输入

> "这个PPT太难搞了，我想让你为我做个PPT，明天要介绍产品的，就一个钛合金马扎，我们研发了200多天，开了200次产品会就为了精益求精，他主要成分就是钛合金，和常见的马扎功能一样，但是防水、耐磨、不易损坏，承担了这些优势的情况下还很轻，你为我做PPT把。"

### 拆分结果

```
【拆分结果】

## 块 1：用户（"我"）
  角色：requester（需求方）
  目的：明天要介绍产品
  诉求：
    1. 做一个PPT（核心交付物）
    2. 介绍钛合金马扎产品
    3. 研发周期：200多天
    4. 产品会议：200次
    5. 品质追求：精益求精
    6. 主要成分：钛合金
    7. 功能：与常见马扎同质
    8. 优势：防水、耐磨、不易损坏
    9. 附加优势：轻便（同比质量小）
  动机：用户觉得PPT太难做

## 块 2：执行者（"你"）
  角色：executor（执行方）
  目的：制作一个符合用户诉求的PPT
  诉求：
    1. 使用技能或MCP等进行完整的PPT制作
    2. 涵盖产品核心卖点（钛合金材质、轻便耐用）
    3. 体现研发投入（200天、200次会议）
    4. 突出精益求精的品质追求
  动机：块1的所有要求

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

【确认询问】
以上拆分是否完整准确？如有遗漏或错误，请补充或纠正。
```


path: references/json_schema.md
content: # JSON 结构规范

> **加载时机**：生成或更新能力级/规则级 json 时加载

---

## 一、层级关系

```
              ┌─────────────────────────────┐
              │        规则级 json           │  ← 上层抽象
              │  • 粒度粗，覆盖一类任务      │
              │  • 由能力级凝练/统合生成      │
              │  • 内嵌 capability_refs[]    │
              └──────────┬──────────────────┘
                         │ 引用 / 渐进加载
            ┌────────────┼────────────┐
            ▼            ▼            ▼
    ┌──────────┐  ┌──────────┐  ┌──────────┐
    │能力级json│  │能力级json│  │能力级json│  ← 原子单元
    └──────────┘  └──────────┘  └──────────┘
```

**规则级 > 能力级**：规则级是上层抽象，能力级是原子单元。

---

## 二、能力级 json（原子单元）

### 生成时机

仅当规则级和能力级均不命中时，经模型思考生成步骤并**执行完成后**，才生成新能力级 json。

### 通用化规则

**通用化 ≠ 抽象提炼**，而是**字段替换**——用占位符替换具体信息，保留步骤结构和粒度。

| 原始具体内容 | 通用化后 |
|---|---|
| `"介绍钛合金马扎产品"` | `"介绍[产品名称]"` |
| `"收集钛合金材料参数"` | `"收集[产品核心参数]"` |
| `"明天下午3点前交付"` | `"在[截止时间]前交付"` |
| `"导出为微信公众号格式"` | `"导出为[目标格式/平台]"` |

**原则**：
- 保留步骤粒度（细节步骤**不**合并）
- 只替换「值」，不改变「结构」
- 步骤数量、并行关系、milestone 标记全部保留
- 文件名格式：`{动词}_{对象类型}_v{n}.json`

### 数据结构

```json
{
  "id": "make_product_ppt_v1",
  "type": "capability",
  "name": "制作产品介绍PPT",
  "version": "1.0.0",
  "created_at": "2026-05-22",
  "description": "从零制作一份产品介绍PPT的完整步骤，通用化版本",
  "generic_params": ["[产品名称]", "[核心参数]", "[截止时间]", "[目标格式]", "[目标受众]"],
  "steps": [
    {
      "id": "s1",
      "name": "收集资料",
      "action": "搜索/整理[产品名称]相关资料和[核心参数]",
      "parallel_group": null,
      "milestone": true,
      "dependency_heat": 0,
      "depends_on": [],
      "constraint_level": "none",
      "source": "focus"
    },
    {
      "id": "s2",
      "name": "设计大纲",
      "action": "根据资料设计PPT结构与章节",
      "parallel_group": null,
      "milestone": true,
      "dependency_heat": 9,
      "depends_on": ["s1"],
      "constraint_level": "none",
      "source": "focus"
    },
    {
      "id": "s3a",
      "name": "制作内容页",
      "action": "填充正文幻灯片内容",
      "parallel_group": "pg1",
      "milestone": false,
      "dependency_heat": 8,
      "depends_on": ["s2"],
      "constraint_level": "none",
      "source": "focus"
    },
    {
      "id": "s3b",
      "name": "设计视觉风格",
      "action": "确定配色/字体/模板风格",
      "parallel_group": "pg1",
      "milestone": false,
      "dependency_heat": 5,
      "depends_on": ["s2"],
      "constraint_level": "soft",
      "source": "focus"
    },
    {
      "id": "s3c",
      "name": "AI生成备选视觉方案",
      "action": "用AI工具生成3个不同风格的视觉草稿供选择",
      "parallel_group": "pg1",
      "milestone": false,
      "dependency_heat": 4,
      "depends_on": ["s2"],
      "constraint_level": "none",
      "source": "divergent_enhanced"
    },
    {
      "id": "s4",
      "name": "审核修改",
      "action": "检查内容准确性与视觉一致性",
      "parallel_group": null,
      "milestone": true,
      "dependency_heat": 7,
      "depends_on": ["s3a", "s3b"]
    },
    {
      "id": "s5",
      "name": "导出PPT",
      "action": "导出为[目标格式]",
      "parallel_group": null,
      "milestone": false,
      "dependency_heat": 3,
      "depends_on": ["s4"]
    }
  ],
  "tags": ["ppt", "内容制作", "产品介绍"]
}
```

### 字段说明

| 字段 | 必填 | 说明 |
|------|:----:|------|
| `id` | ✅ | 唯一标识，格式 `{动词}_{对象}_v{版本}` |
| `type` | ✅ | 固定为 `"capability"` |
| `name` | ✅ | 人类可读名称 |
| `version` | ✅ | 语义化版本号 |
| `created_at` | ✅ | 创建日期 |
| `description` | ✅ | 能力描述 |
| `generic_params` | ✅ | 通用化参数占位符列表 |
| `steps` | ✅ | 步骤数组（见下方） |
| `tags` | ✅ | 标签，用于归类 |

**steps 子字段**：

| 字段 | 必填 | 说明 |
|------|:----:|------|
| `id` | ✅ | 步骤唯一标识（如 `s1`, `s3a`） |
| `name` | ✅ | 步骤名称 |
| `action` | ✅ | 具体操作描述（含通用化占位符） |
| `parallel_group` | ✅ | 并行组标识，`null` 表示串行 |
| `milestone` | ✅ | 是否为里程碑步骤 |
| `dependency_heat` | ✅ | 关联热度 0-10 |
| `depends_on` | ✅ | 依赖的前置步骤 id 数组 |
| `constraint_level` | ❌ | 约束强度：`critical` / `soft` / `none`，对应🔴🟡⚪ |
| `source` | ❌ | 步骤来源：`focus` / `divergent_enhanced`，聚焦步骤可不填（默认 focus） |

---

## 三、规则级 json（统合上层）

### 生成时机

同类能力级 json **≥ 5 份** 后，通过定时任务/自动化/用户主动要求凝练生成。

### 数据结构

```json
{
  "id": "rule_ppt_v1",
  "type": "rule",
  "name": "PPT类任务规则",
  "version": "1.0.0",
  "created_at": "2026-05-22",
  "description": "统合所有PPT相关能力级json，提炼核心思考链",
  "source_capability_count": 5,
  "capability_refs": [
    { "id": "make_product_ppt_v1", "name": "制作产品介绍PPT" },
    { "id": "make_tech_ppt_v1",    "name": "制作技术方案PPT" },
    { "id": "design_slide_v1",     "name": "设计幻灯片" },
    { "id": "export_ppt_v1",       "name": "导出PPT" },
    { "id": "review_ppt_v1",       "name": "审核PPT" }
  ],
  "condensed_steps": [
    {
      "id": "r1",
      "name": "资料与大纲",
      "milestone": true,
      "parallel_group": null,
      "maps_to": ["make_product_ppt_v1.s1", "make_product_ppt_v1.s2"],
      "load_capability_if_detail_needed": "make_product_ppt_v1"
    },
    {
      "id": "r2",
      "name": "制作与设计（可并行）",
      "milestone": false,
      "parallel_group": "rp1",
      "maps_to": ["make_product_ppt_v1.s3a", "make_product_ppt_v1.s3b"],
      "load_capability_if_detail_needed": "design_slide_v1"
    },
    {
      "id": "r3",
      "name": "审核与导出",
      "milestone": true,
      "parallel_group": null,
      "maps_to": ["make_product_ppt_v1.s4", "make_product_ppt_v1.s5"],
      "load_capability_if_detail_needed": "export_ppt_v1"
    }
  ],
  "tags": ["ppt", "规则汇总"]
}
```

### 字段说明

| 字段 | 必填 | 说明 |
|------|:----:|------|
| `id` | ✅ | 唯一标识，格式 `rule_{类别}_v{版本}` |
| `type` | ✅ | 固定为 `"rule"` |
| `name` | ✅ | 人类可读名称 |
| `version` | ✅ | 语义化版本号 |
| `created_at` | ✅ | 创建日期 |
| `description` | ✅ | 规则描述 |
| `source_capability_count` | ✅ | 来源能力级 json 数量 |
| `capability_refs` | ✅ | 来源能力级引用数组（id + name） |
| `condensed_steps` | ✅ | 压缩步骤数组（见下方） |
| `tags` | ✅ | 标签 |

**condensed_steps 子字段**：

| 字段 | 必填 | 说明 |
|------|:----:|------|
| `id` | ✅ | 步骤唯一标识 |
| `name` | ✅ | 步骤名称 |
| `milestone` | ✅ | 是否为里程碑 |
| `parallel_group` | ✅ | 并行组标识，`null` 表示串行 |
| `maps_to` | ✅ | 映射到哪些能力级的具体步骤（格式：`{能力级id}.{步骤id}`） |
| `load_capability_if_detail_needed` | ✅ | 需要细节时加载的能力级 json id |

---

## 五、脚本辅助操作

> 以下操作可通过 `scripts/json_manager.py` 自动化完成，AI 调用时优先使用脚本而非手动 Read/Write。

### 5.1 扫描匹配

```bash
# 按关键词搜索 json 库（规则级 + 能力级）
python scripts/json_manager.py scan --keywords ppt 制作 --top 5
# 输出: 匹配的 json 列表，含分数、类型、文件路径
```

### 5.2 归类统计

```bash
# 统计所有能力级 json 的 tag 分布，判断是否达到规则级阈值
python scripts/json_manager.py categorize --threshold 5
# 输出: 各 tag 分组及数量，ready_for_rule 标识
```

### 5.3 通用化（字段替换）

```bash
# params 模式：AI 决定替换映射，脚本执行替换
python scripts/json_manager.py generalize \
  --input ~/.workbuddy/skills/.standardization/semantic-split/data/capabilities/xxx_concrete.json \
  --params "钛合金马扎=[产品名称]" "材料参数=[核心参数]" "明天=[截止时间]" \
  --output ~/.workbuddy/skills/.standardization/semantic-split/data/capabilities/xxx_v1.json

# auto 模式：仅收集已有的中括号占位符（不替换）
python scripts/json_manager.py generalize --input xxx.json --auto
```

### 5.4 规则级生成

```bash
# 按标签自动选取同类能力级 json 生成规则级
python scripts/json_manager.py rule-gen --tag ppt --output rule_ppt_v1.json

# 指定多个文件生成
python scripts/json_manager.py rule-gen --files a.json b.json c.json
```

### 5.5 创建与验证

```bash
# 创建骨架文件
python scripts/json_manager.py create --type capability --name make_report_v1

# 验证格式
python scripts/json_manager.py validate --file ~/.workbuddy/skills/.standardization/semantic-split/data/capabilities/make_report_v1.json
```

---

## 四、JSON 存储结构

```
skills/.standardization/semantic-split/data/    ← 铁律4：产出物不嵌入技能目录
├── capabilities/                     # 能力级 json 存储目录
│   ├── make_product_ppt_v1.json
│   └── ...
└── rules/                            # 规则级 json 存储目录
    ├── rule_ppt_v1.json
    ├── rule_report_v1.json
    └── ...
```


path: references/loading_decision_tree.md
content: # 渐进加载决策树

> **加载时机**：进入 SKILL.md 步骤 6 时**必须加载**

---

## 决策树（完整版）

```
收到用户任务
    │
    ▼
① 先扫描规则级 json 库（skills/.standardization/semantic-split/data/rules/）
    │
    ├─ ✅ 命中规则级（完全匹配）
    │       └─→ 用规则级 condensed_steps 生成规划 → 展示
    │               │
    │               ▼
    │           【询问用户】是否按此规划执行？
    │               ├─ 确认执行 → 执行
    │               │            ✗ 不启动模型思考，✗ 不生成新能力级 json
    │               └─ 有调整   → 按调整修改规划 → 再次展示
    │                               │
    │                               ▼
    │                           【询问用户】调整是否要：
    │                               A. 更新原有能力级 json（改写对应步骤）
    │                               B. 创建新的能力级 json（保留原有）
    │                               C. 仅本次使用，不更新 json
    │
    ├─ ✅ 命中规则级（部分匹配，前N步适用）
    │       └─→ 规则级前N步 + 通过 capability_refs 全量加载后续能力级
    │           → 生成规划 → 展示
    │           │
    │           ▼
    │       【询问用户】是否按此规划执行？（同上分支逻辑）
    │
    ├─ ⚠️ 命中规则级但粒度太粗（需要细节）
    │       └─→ 通过 load_capability_if_detail_needed 渐进加载对应能力级
    │           补充细节步骤 → 拼装规划 → 展示
    │           │
    │           ▼
    │       【询问用户】是否按此规划执行？（同上分支逻辑）
    │
    └─ ❌ 规则级完全不命中
            │
            ▼
         ② 扫描能力级 json 库（skills/.standardization/semantic-split/data/capabilities/）
                │
                ├─ ✅ 命中能力级（完全/组合匹配）
                │       └─→ 直接复用/拼装能力级 json → 生成规划 → 展示
                │               │
                │               ▼
                │           【询问用户】是否按此规划执行？（同上分支逻辑）
                │               ✗ 不启动模型思考，✗ 不生成新能力级 json
                │
                └─ ❌ 能力级也不命中
                        │
                        ▼
                     ③ 模型思考 → 生成步骤规划 → 展示
                        │
                        ▼
                    【询问用户】是否按此规划执行？
                        ├─ 确认执行
                        │       └─→ 执行任务
                        │               │
                        │               ▼
                        │           执行完成后：
                        │           生成通用化能力级 json ✅
                        │           （抹去具体信息特征，保持当前步骤粒度）
                        │
                        └─ 有调整   → 按调整修改规划 → 再次展示
                                        │
                                        ▼
                                    【询问用户】
                                        A. 按调整后版本执行（执行完生成新能力级 json）
                                        B. 仅本次使用，不生成 json
```

---

## JSON 生成条件总结

| 场景 | 行为 | 生成新能力级 json？ |
|------|------|:---:|
| 命中规则级（完全） | 直接复用 | ✗ |
| 命中规则级（部分 + 能力级加载） | 拼装复用 | ✗ |
| 命中规则级（粗粒度 + 渐进补充） | 补充拼装 | ✗ |
| 命中能力级（完全/组合） | 直接复用 | ✗ |
| 命中 + 用户有调整 | 按调整执行 | 取决于用户选择 A/B/C |
| 不命中 + 用户确认执行 | 模型思考 → 执行 | ✅ 执行完成后生成 |
| 不命中 + 用户确认重新规划 | 模型思考 → 执行 | ✅ 执行完成后生成 |
| 不命中 + 用户选择仅本次使用 | 模型思考 → 执行 | ✗ |

---

## json 匹配规则

**如何判断是否"命中"**：

1. **规则级匹配**：用户任务的核心动词 + 对象类型 与规则级的 `tags` 或 `name` 匹配
   - 例：用户说"帮我做个PPT" → 匹配 `rule_ppt_v1`（tags 含 "ppt"）
2. **能力级匹配**：更细粒度，匹配能力级的 `name`、`description`、`tags`
   - 例：用户说"导出PPT" → 匹配 `export_ppt_v1`
3. **组合匹配**：多个能力级 json 拼装覆盖用户全部诉求
   - 例：用户说"做个PPT并导出为PDF" → 组合 `make_product_ppt_v1` + `export_ppt_v1`
4. **部分匹配**：规则级/能力级的前 N 步适用，后续步骤需加载其他 json
5. **完全不命中**：所有 json 均无法覆盖用户诉求的 50% 以上

### 脚本辅助匹配

AI 执行步骤 6 时，应使用脚本自动扫描匹配：

```bash
# ① 扫描规则级
python scripts/json_manager.py scan --keywords <任务关键词> --type rule --top 3

# ② 规则级不命中时，扫描能力级
python scripts/json_manager.py scan --keywords <任务关键词> --type capability --top 5

# ③ 均不命中时，检查归类统计是否需要凝练规则级
python scripts/json_manager.py categorize --threshold 5
```


path: references/planning_rules.md
content: # 串并行规划规则

> **加载时机**：模型思考生成步骤时加载（决策树分支③）

---

## 一、原子步骤拆解

将 request 中的主要动作拆解为**原子步骤**（不可再分的最小执行单元）。

| 规则 | 说明 | 示例 |
|------|------|------|
| 动作→步骤 | 每个独立动作对应一个步骤 | "做PPT" → 收集资料 / 设计大纲 / 制作PPT / 审核 / 导出 |
| 前置挖掘 | 从 motivation 中提取隐含前置步骤 | "钛合金成分" → 增加"材质专题页"；"研发200天" → 增加"研发故事" |
| 时间倒推 | 根据 purpose 时间约束倒推交付步骤 | "明天要" → 最后一步必须是"导出PPT" |

## 二、串并行标记

- **无数据依赖且不冲突**的步骤标记为可并行，归入同一 `parallel_group`
- `parallel_group` 相同的步骤可同时执行
- 无标记的步骤按序串行执行

**标记方式**：
```
步骤 4a: 制作内容页 ── parallel_group: pg1 ── milestone: ❌
步骤 4b: 设计视觉风格 ── parallel_group: pg1 ── milestone: ❌
```

## 三、关联热度（dependency_heat）

步骤间的**关联热度**表示两个步骤之间的数据依赖强度（0-10），用于指导渐进加载时的步骤拆分和合并决策。

| 热度值 | 含义 | 示例 |
|--------|------|------|
| 0 | 无依赖，完全独立 | "选模板" 与 "定配色" |
| 1-3 | 弱依赖，可延迟或跳过 | "导出" 依赖 "审核" |
| 4-6 | 中等依赖，通常需顺序执行 | "制作内容页" 依赖 "大纲" |
| 7-9 | 强依赖，必须严格顺序 | "大纲" 依赖 "资料收集" |
| 10 | 强耦合，不可拆分 | 同一步骤内的子操作 |

## 四、里程碑标记（milestone）

- 如果某步骤**失败会导致整个任务失败**，标记为 `milestone: true`
- milestone 步骤失败时，**中止**后续步骤，报告失败原因
- 非 milestone 步骤失败时，可选择跳过继续

## 五、规划输出格式

```
【规划结果】

📌 任务：[任务名称]
⏰ 约束：[时间/资源约束]

执行步骤：
  步骤 1: [名称] ── serial ── milestone: ✅/❌
    action: [具体操作]
    depends_on: [依赖步骤]
    dependency_heat: [关联热度]

  步骤 2a: [名称] ── parallel_group: pg1 ── milestone: ✅/❌
    action: [具体操作]
    depends_on: [依赖步骤]
    dependency_heat: [关联热度]

  步骤 2b: [名称] ── parallel_group: pg1 ── milestone: ✅/❌
    ...

  步骤 3: [名称] ── serial ── milestone: ✅/❌
    ...

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
来源：[规则级json / 能力级json / 模型思考]
【询问用户】是否按此规划执行？如有调整请说明。
  1. 确认执行
  2. 有调整（说明调整内容）
  3. 要求重新规划/重新思考
```

**用户选择处理**：
- **确认执行** → 执行任务
- **有调整** → 按用户意见修改规划 → 再次展示 → 再次询问
- **有调整后的额外询问** → 调整是否要：
  - A. 更新原有能力级 json（改写对应步骤）
  - B. 创建新的能力级 json（保留原有）
  - C. 仅本次使用，不更新 json
- **要求重新规划** → 忽略已有 json，启动模型重新思考生成步骤

---

## 六、双视角推理与整合规则

> 本规则仅在决策树分支③（模型思考）时生效。详见 `constraint_annotation.md` 第四节。

### 6.1 聚焦方案生成规则

1. 对每个 5W2H 维度，选择「最窄/最保守/最直接」的值
2. 严格遵守所有🔴硬约束（任何步骤不可违反）
3. 只使用已验证、低学习成本的方法（不引入新工具）
4. 时间窗口取截止时间的一半（如周五截止 → 周三前完成初稿）
5. 每个步骤不超过 30 分钟可完成
6. 输出格式：步骤列表，每个步骤含 action / depends_on / dependency_heat

### 6.2 发散方案生成规则

1. 对每个 5W2H 维度，选择「最宽/最大胆/最间接」的值
2. 🔴硬约束可轻微突破，但必须在步骤中标注 🌟 和「风险：...」，并提供备用方案
3. 引入至少一个非惯用工具或方法（如 AI 生成、手绘、录音口述）
4. 时间上尝试「反向工作法」（先做最不可能的部分）
5. 包含一个「如果无限资源会怎么做」的变体步骤
6. 输出格式：步骤列表 + 创新点列表

### 6.3 整合规则

1. **以聚焦方案为骨架**：整合后的步骤顺序 = 聚焦方案顺序
2. **嵌入发散创新点**：
   - 遍历发散方案的每个创新点
   - 判断：该创新点对应聚焦方案的哪个步骤？（通过语义相似度）
   - 若找到对应步骤 → 将该创新点作为「🌟增强」嵌入该步骤
   - 若找不到对应步骤 → 作为独立🌟步骤插入最合适位置
3. **标注来源**：所有🌟步骤注明「增强：来自发散方案」
4. **风险说明**：若🌟步骤涉及🔴硬约束突破，附「⚠️ 风险：...」
5. **输出**：单一的整合后步骤列表（不输出双方案对比）

### 6.4 工作包分解规则

对整合后的步骤列表，进行工作包分解：

**聚焦式分解**（适用于大多数任务）：
- 粒度：每个工作包 2-4 小时可完成
- 格式：`WP{n}: [任务描述] (预计耗时，前置：WP{x},WP{y})`
- 每 3-5 个 WP 设置一个检查点：`📍 检查点：验证[XX]`

**探索式分解**（适用于创意/研究类任务）：
- 格式：`模块A/B/C：[探索内容]`
- 不要求严格顺序，可并行探索
- 每个模块标注「探索目标」和「成功标准」

---

## 七、约束遵循检查

生成整合步骤后、输出前，执行以下检查：

| 检查项 | 修正动作 |
|--------|---------|
| 是否有步骤违反了🔴硬约束？ | 如有 → 重新生成该步骤 |
| 是否有🔴硬约束未被任何步骤覆盖？ | 如有 → 补充步骤 |
| 发散创新点（🌟步骤）是否标注了风险？ | 如涉及🔴突破 → 必须标注 |
| 工作包粒度是否超过4小时？ | 如超过 → 继续拆分 |


path: references/split_rules.md
content: # 语义拆分规则

> **加载时机**：步骤 2、步骤 3 首次执行时加载

---

## 一、划分块（Block）

**识别主语，划分语义块：**

| 主语类型 | 识别方式 | 块标记 |
|---------|---------|--------|
| 用户（"我"） | 说话者本人 | `块1：用户` |
| AI助手（"你"） | 执行者、帮助者 | `块2：执行者` |
| 第三方（"他/她/它"） | 提及的其他角色 | `块3：第三方-N` |

**块内元素提取：**

| 元素 | 定义 | 示例 |
|-----|------|-----|
| **目的 (Purpose)** | 最终要达成的目标 | "明天要介绍产品" |
| **行为/诉求 (Request)** | 需要执行的具体操作或交付物 | "做一个PPT"、"写一份报告" |
| **动机 (Motivation)** | 为什么会产生这个需求 | "PPT太难做了"、"时间紧迫" |

---

## 二、诉求聚合（Request Aggregation）

将同一目的下的所有诉求点聚合，包括：
- 核心诉求（主要交付物）
- 支撑信息（背景、条件、约束）
- 附加细节（特征、规格、要求）

---

## 三、常见主语映射表

| 文本中的词 | 映射为 | 备注 |
|-----------|-------|------|
| 我、咱们、俺 | 用户 | 说话者本人 |
| 你、您 | 执行者 | AI助手 |
| 我们 | 用户（含其团队） | 视为用户群体 |
| 他/她/它 + [名称] | 第三方 | 需标注具体身份 |
| [公司/产品名] | 第三方 | 实体对象 |

---

## 四、边界情况处理

| 情况 | 处理方式 |
|-----|---------|
| 单用户无明确主语 | 默认主语为"用户" |
| 多个并列诉求 | 同一块内编号列表 |
| 隐含目的 | 根据上下文推断，动机标注"[推断]" |
| 情绪/语气词 | 归入动机，标注"[情绪]" |
| 时间/预算约束 | 归入目的或诉求约束条件 |
| json 库为空 | 跳过①②，直接进入③模型思考 |
| json 部分匹配 | 取最佳匹配，渐进加载补充 |
| 约束强度冲突 | 同一维度出现不同约束词 → 按最高强度处理（🔴>🟡>⚪） |
| 举例内容干扰 | 「比如/例如」后内容标记为[EXAMPLE]，不作为核心约束 |

---

## 五、5W2H 与约束标注提取规则

> 本节为步骤 3 的详细提取规则，供模型参考。

对每个块，逐句分析：

```
对于 [主语] 说的每句话：
  → 目的：这句话要达成什么？（找"为了"、"要"、"想"等关键词）
  → 行为：需要做什么具体操作？（找动词）
  → 动机：为什么会这么说？（找原因、背景、情绪）
  → 5W2H：这句话对应哪个维度？（Why/What/Who/Where/When/How/How much）
  → 约束强度：包含约束词吗？（🔴必须/🟡尽量/⚪未提及）
```

**5W2H 提取规则**（详见 `task_type_defaults.md`）：
- 用户明确提供 → 覆盖默认值，约束强度按约束词判断
- 用户未提供 → 保留步骤 2.5 填入的默认值，标注 `[推断]`
- 阻力：从「但是/不过/担心/怕/难/卡」提取，单独记录


path: references/task_type_defaults.md
content: # 任务类型默认映射表

> **加载时机**：步骤 2.5 首次执行时加载；后续可缓存

---

## 使用规则

- 用户任务文本未能提供某 5W2H 维度时，使用本表填入默认值
- 用户明确提供的维度 → 覆盖默认值，约束强度按约束词判断
- 默认值标注 `[推断]`，最终输出时保留此标注
- 本表仅为启发式参考，模型可根据上下文调整默认值

---

## 任务类型 1：制作 PPT

| 维度 | 默认值 | 说明 |
|------|--------|------|
| Why | 有效传达信息 | 核心动机 |
| What | 结构清晰、视觉简洁 | 交付物标准 |
| Who | 目标听众（从上下文推断或设为"决策者"） | 受众 |
| When | 截止时间（若未给，设为"尽快"） | 时间约束 |
| Where | 会议/线上 | 场景 |
| How | 使用常用演示工具 | 方法 |
| How much | 页数10-20页、说服力评分 | 量化指标 |
| 阻力 | 内容组织困难、时间不足 | 常见障碍 |

---

## 任务类型 2：填写周报

| 维度 | 默认值 | 说明 |
|------|--------|------|
| Why | 向上汇报进展 | 核心动机 |
| What | 完成事项、问题、计划 | 交付物内容 |
| Who | 直属上级 | 受众 |
| When | 每周五下班前 | 时间约束 |
| Where | 公司周报系统 | 场景 |
| How | 按公司模板填写 | 方法 |
| How much | 覆盖所有关键项目、数据准确 | 量化指标 |
| 阻力 | 记不清做了什么、亮点不够 | 常见障碍 |

---

## 任务类型 3：安排今日行程

| 维度 | 默认值 | 说明 |
|------|--------|------|
| Why | 提高效率、减少遗漏 | 核心动机 |
| What | 任务清单+时间块 | 交付物 |
| Who | 自己 | 执行者 |
| When | 今天 | 时间约束 |
| Where | 工作地点 | 场景 |
| How | 优先级排序+日历锁定 | 方法 |
| How much | 完成率达到80% | 量化指标 |
| 阻力 | 优先级不清、干扰打断 | 常见障碍 |

---

## 任务类型 4：写邮件

| 维度 | 默认值 | 说明 |
|------|--------|------|
| Why | 清晰沟通、促成行动 | 核心动机 |
| What | 主题、背景、请求、礼貌结尾 | 交付物内容 |
| Who | 收件人（从上下文或默认"对方"） | 受众 |
| When | 尽快 | 时间约束 |
| Where | 邮件客户端 | 场景 |
| How | 标准邮件格式 | 方法 |
| How much | 回复率或行动采纳率 | 量化指标 |
| 阻力 | 语气不当、信息遗漏 | 常见障碍 |

---

## 任务类型 5：策划活动

| 维度 | 默认值 | 说明 |
|------|--------|------|
| Why | 达成特定目标（从上下文推断） | 核心动机 |
| What | 活动方案、流程、物料 | 交付物 |
| Who | 目标参与者（从上下文推断） | 受众 |
| When | 未指定（需后续确认） | 时间约束 |
| Where | 未指定（需后续确认） | 场景 |
| How | 标准活动策划流程 | 方法 |
| How much | 预算未指定 | 量化指标 |
| 阻力 | 资源不足、协调困难 | 常见障碍 |

---

## 未匹配任何类型时的通用默认值

| 维度 | 默认值 | 约束强度 |
|------|--------|---------|
| Why | 完成用户提出的任务 | ⚪ |
| What | 未指定（需用户补充） | ⚪ |
| Who | 用户本人 | ⚪ |
| When | 尽快 | 🟡 |
| Where | 当前工作场景 | ⚪ |
| How | 使用常用工具和方法 | ⚪ |
| How much | 未指定 | ⚪ |
| 阻力 | 未识别 | — |


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