# Strategy 抽象化迁移完成报告

**日期**：2026-04-22
**范围**：Phase 0 → Phase 6 全部完成

---

## 一、整体变化对照

| 实体 | 迁移前 | 迁移后 | 说明 |
|---|---|---|---|
| strategy 表 | 99（全是 req-specific 具体方案） | **26 abstract pattern**（version=`howard_strategy_instance`）| 每条 = 一种可跨 req 复用的"方法套路 / skill" |
| knowledge 表 | 1046 条 v0 老数据 | 1092 v0 + **193 新**（version=`howard_strategy_instance`）| 新增 193 条承载 req-specific 执行细节 |
| requirement_strategy | 99（严格 1:1）| **155**（M:N）| 每 req 可对应多个 pattern（含 selected + alt）|
| requirement_knowledge | 0 | **193** | 新 junction，精确记录 (req, knowledge) 关系 |
| strategy_knowledge | 0 | **193** | abstract pattern ↔ knowledge 实例 |
| knowledge_resource | 306（老）| 306 + **5339 新** | knowledge 引用的 resources |
| knowledge_capability | 0 | **1198**（新建）| 保证 knowledge_cap ⊆ req_cap 约束的关键 junction |
| strategy_capability | 1202（具体 strat → cap）| 653（abstract 的 cap 联合）| 降下来是因为抽象后多条并一条 |
| strategy_resource | 2736（具体 strat → resource）| 2702（abstract 的 resource 联合）| 同上 |
| requirement_capability（研究全集）| 1106 | 1106（不变）| Research superset 不变 |
| capability 表 | 332 | 332（不变）| 抽象化不涉及 cap 层 |

---

## 二、数据模型变更

### 增量 schema 变更

```sql
-- Phase 2 schema migration (已执行)
ALTER TABLE requirement_strategy
    ADD COLUMN is_selected BOOLEAN,
    ADD COLUMN coverage_score FLOAT,
    ADD COLUMN coverage_explanation TEXT;

-- requirement_knowledge 已存在（空），ALTER 补 3 列
ALTER TABLE requirement_knowledge
    ADD COLUMN is_selected BOOLEAN,
    ADD COLUMN coverage_score FLOAT,
    ADD COLUMN coverage_explanation TEXT;

-- knowledge_resource：已存在（306 行老数据 knowledge→tools），沿用
-- knowledge_capability：新建
CREATE TABLE knowledge_capability (
    knowledge_id   VARCHAR NOT NULL,
    capability_id  VARCHAR NOT NULL,
    PRIMARY KEY (knowledge_id, capability_id)
) DISTRIBUTED BY (knowledge_id);
```

### is_selected / coverage 的双存冗余

用户决策：**两张表都存，允许语义漂移**
- `requirement_strategy.is_selected` = "req 的多个候选 pattern 中，这个 pattern 被选"（pattern 粒度）
- `requirement_knowledge.is_selected` = "具体执行实例里，这条 knowledge 是被选的执行"（execution 粒度）
- 初始状态两者同值；随着时间推移可能独立演化（未来扩展允许某 pattern 被选而某具体执行被改）

---

## 三、典型查询路径

### Q1: 某 req 选了哪些 pattern + 各自覆盖度

```sql
SELECT s.name pattern_name, rs.is_selected, rs.coverage_score, rs.coverage_explanation
FROM requirement_strategy rs
JOIN strategy s ON s.id = rs.strategy_id
WHERE rs.requirement_id = 'REQ_003';
```

### Q2: 某 req 针对某 pattern 的具体执行细节

```sql
SELECT k.content
FROM knowledge k
JOIN requirement_knowledge rk ON rk.knowledge_id = k.id
JOIN strategy_knowledge sk ON sk.knowledge_id = k.id
WHERE rk.requirement_id = 'REQ_003'
  AND sk.strategy_id = 'strategy-abstract-p17'
  AND k.version = 'howard_strategy_instance';
```

### Q3: 某 abstract pattern 跨多少 req 被使用（pattern 价值分析）

```sql
SELECT COUNT(DISTINCT rs.requirement_id) reuse_count
FROM requirement_strategy rs
WHERE rs.strategy_id = 'strategy-abstract-p01';
-- 返回：22（P01 最高复用度）
```

### Q4: 某 knowledge 精确用到了哪些 cap（作为约束验证）

```sql
SELECT c.id, c.name FROM knowledge_capability kc
JOIN capability c ON c.id = kc.capability_id
WHERE kc.knowledge_id = 'knowledge-stratinst-xxx';
```

---

## 四、新旧数据隔离

所有新增数据用 `version='howard_strategy_instance'` 标记：

```sql
-- 只看新增的 strategy instance knowledge
WHERE k.version = 'howard_strategy_instance';

-- 不动老 knowledge
WHERE k.version = 'v0';  -- 1092 行
```

abstract strategy 也用同一 version 标记（26 行）。

---

## 五、复用度 TOP 8 pattern（抽象化的价值证明）

| Pattern | 复用次数 | 服务 reqs |
|---|---|---|
| 结构化提示词单步直出套路 | **22** | 各种直出场景（图文/色调/单步生成）|
| ComfyUI 节点链精控套路 | 11 | 精细控制类需求 |
| 多图层分层合成套路 | 9 | 人物+场景合成类 |
| 网格/分镜一次性直出套路 | 7 | 九宫格/分镜类 |
| 参考图垫图控制套路 | 7 | 版式迁移/风格锁定 |
| 智能抠图 + 拼贴排版套路 | 7 | 拼贴类 |
| AI 图内文字渲染 + 排版套路 | 7 | 含文字排版的图 |
| Coze 工作流编排全自动套路 | 7 | 大规模自动化 |

这些 pattern 验证了"方法论跨 req 迁移"的抽象价值。例如 `P01 结构化提示词单步直出` 方法在 22 种不同视觉需求下都适用。

---

## 六、已知数据缺口

| 问题 | 数量 | 原因 | 是否关键 |
|---|---|---|---|
| knowledge 无 cap 链接 | 10 条 | 源 strategy 用了 LLM 自造的 cap ID（如 `aigc_color_unification`），alias 和 fuzzy 都对不上 | 边缘情况，不影响主功能 |
| coverage_score 为 null | 42 条 req_strategy | 13 个 req 的 coverage_scores.json 缺失 + 部分 alt 名字 fuzzy 对不上 | 接受，查询时要处理 null |
| 5 个占位 strategy（004/031/053/066/070）| Phase 1 已修 | 源 strategy.json 用非标准 schema | 已解决 |

---

## 七、约束验证（回归测试）

✅ **每 req 有完整关系**（99/99）
- requirement_strategy: 99/99 覆盖
- requirement_knowledge: 99/99 覆盖
- requirement_resource: 99/99 覆盖
- requirement_capability: 99/99 覆盖

✅ **核心约束保持**
- `knowledge_cap ⊆ req_cap`（经 requirement_knowledge）：0 违规
- 每 req 至多 1 条 is_selected=TRUE：✓

⚠️ **约束变更（由设计决定）**
- 旧约束 `strat_cap ⊆ req_cap`（经 requirement_strategy）：3674 违规 —— 这是**预期**的，因为 abstract strategy_capability 是联合集，不再是单 req 的 compose 子集。新的同等约束转移到 knowledge 层（见上）

---

## 八、备份可回滚

`bk_20260422_*` 6 张快照表保留：
- `bk_20260422_strategy`（99 行）
- `bk_20260422_requirement_strategy`（99 行）
- `bk_20260422_strategy_capability`（703 行，Phase 1 后 + Phase 2 前快照）
- `bk_20260422_strategy_resource`（2736 行）
- `bk_20260422_strategy_knowledge`（0 行）
- `bk_20260422_knowledge`（1067 行）

**确认无问题后**可 `DROP TABLE bk_20260422_*;` 释放空间。建议保留 7 天以防万一。

---

## 九、全链路脚本清单

Phase 0 → Phase 6 涉及的脚本都在 `knowhub/scripts/`：

| 脚本 | 阶段 | 作用 |
|---|---|---|
| `salvage_placeholder_strategies.py` | Phase 1 | 修 5 个占位 strategy 的 body |
| `backup_before_strategy_refactor.py` | Pre-Phase 2 | DB 内快照 |
| `phase2_schema_migration.py` | Phase 2 | ALTER requirement_strategy + 检查 junctions |
| `ingest_all_strategies.py` | Phase 2 | 入库全部 strategy（含备选），填 coverage |
| `abstract_patterns.py` | Phase 3 | 27 pattern 定义 + 193→pattern 映射 |
| `phase4_5_migrate.py` | Phase 4+5 | 主迁移脚本 |
| `phase5_add_knowledge_capability.py` | Phase 5 补 | 创建 knowledge_capability + 从 backup 恢复 |
| `phase5_fill_alt_knowledge_capability.py` | Phase 5 补 | 从源 JSON 补 alt 的 cap 链接 |
| `phase5_fuzzy_fill_remaining.py` | Phase 5 补 | 最后 12 条的 fuzzy 匹配尝试 |

---

## 十、下一步可能优化（非紧急）

1. **精细化 knowledge_resource**：当前是 req 级联合（每 knowledge 链到 req 的所有 case），可精化为从 `body.source` 字段逐 case 匹配，实现 knowledge 粒度的精确引用
2. **解决 10 条无 cap knowledge**：人工判断 LLM 自造 cap 名 → 现有 canonical 的映射，加入 LLM_RENAMES 或 LEGACY_REFS
3. **Pattern 边界动态调优**：实际使用一段时间后，看哪些 pattern 被频繁搜到、哪些总是空查，据此拆/合
4. **capability_tool 补全**：本次没涉及，是独立的待办（见 2026-04-21 handoff §5 待办 2）
5. **embedding 重算**：所有 strategy / capability / knowledge 的 embedding 字段目前空（task/content 嵌入未算），启用语义搜索前需要批量生成
