# Ontology Engine 包化设计 — 二层架构与迁移路标

> **V37.9.99-pkg / 2026-06-02 · Phase 5 chunk 1** + **V37.9.104 / 2026-06-04 · chunk 4 (Extension Guide + 最小消费方 demo)**
> 终极目标 `pip install <ontology-engine>` + 项目级 YAML 配置的奠基文档。
> 当前基础: Phase 3 ONTOLOGY_MODE=on / Phase 4 P1-P3 evaluate_policy + three_gate / 90 不变式 / 23 元规则 / governance v3.56。
> chunk 4 交付: `examples/minimal_consumer/` (WeatherBot 真消费方) + `docs/ontology_engine_extension_guide.md` + `test_ontology_extension_demo.py` (12 端到端单测)。

---

## 1. 终极目标

让**任何 Agent Runtime 项目**只需：

```bash
pip install openclaw-ontology-engine        # 装引擎 (Layer 1)
export ONTOLOGY_CONFIG_DIR=/myproject/ontology   # 指向自己的 YAML (Layer 2)
openclaw-ontology-audit                      # 跑治理审计
```

就获得**工具治理 + 语义查询 + governance 审计**能力，**无需理解引擎内部**。

核心价值不是"最强 LLM"，而是 **control plane 让任何 LLM 都能安全运行**——这是 V3 路标"别人会扩展"的终极交付物，也是 `docs/articles/ai_partnership_first_principles_zh.md` 第一性原理"协作本质是边界不是信任"的工程兑现。

---

## 2. 二层架构

| 层 | 内容 | 归属 | 当前位置 |
|---|---|---|---|
| **Layer 1 — 引擎 (项目无关)** | `ToolOntology` 类 / `evaluate_policy` / `find_by_domain` / 6 context evaluator dispatch · 5 个 check executor (`file_contains`/`file_not_contains`/`python_assert`/`env_var_exists`/`command_succeeds`) + `run_all` / `run_meta_discovery` MRD 框架 · convergence framework · 三阶段门控 three_gate · 三档特性开关 (off/shadow/on) | **本 pip 包** | `ontology/{engine,governance_checker,convergence,three_gate,diff}.py` |
| **Layer 2 — 配置 (项目特定)** | `tool_ontology.yaml` (工具声明) · `governance_ontology.yaml` (不变式 + 元规则 + check 定义) · `domain_ontology.yaml` · `policy_ontology.yaml` · `convergence_ontology.yaml` · 项目特定 MRD 扫描模式 (jobs_registry / notify.sh 路径等) | **消费方项目** | `ontology/*.yaml` (本仓库自带, 作默认参考) |

**关键判据**：代码是否含**项目特定知识**？
- `_exec_file_contains(check)` 执行 check 定义里的 pattern → 项目无关 → Layer 1
- `governance_ontology.yaml` 里 `INV-MOVESPEED-TCC-001` 守的是本项目的 MOVESPEED 备份 → 项目特定 → Layer 2

---

## 3. Config-Injection 契约（chunk 1 的 keystone）

引擎代码**不绑定**配置所在位置。解析优先级（两个 env 共享语义）：

| 环境变量 | 控制 | 默认 (向后兼容) |
|---|---|---|
| `ONTOLOGY_CONFIG_DIR` | 所有 YAML (`tool_ontology.yaml` / `governance_ontology.yaml` / `domain` / `policy`) 所在目录 | 引擎代码同目录 (`dirname(__file__)`) |
| `ONTOLOGY_PROJECT_ROOT` | governance 的 `file_contains` / `python_assert` 相对路径基准 + MRD 扫描根 | 引擎代码仓库根 (`dirname(dirname(__file__))`) |

```python
# engine.py
def _resolve_config_dir():
    env_dir = os.environ.get("ONTOLOGY_CONFIG_DIR", "").strip()
    return os.path.abspath(os.path.expanduser(env_dir)) if env_dir \
        else os.path.dirname(os.path.abspath(__file__))

# governance_checker.py — 同款 + _resolve_project_root()
```

**细粒度覆盖仍可用**：`ToolOntology(path=...)` / `evaluate_policy(..., path=...)` / `find_by_domain(..., path=...)` 的 `path` 参数优先于 `ONTOLOGY_CONFIG_DIR`，env 只是"未指定 path 时"的兜底。

**为什么这是 keystone**：没有它，pip 装的引擎只能读引擎自己目录下的 YAML（= 本项目的 YAML），消费方无法用自己的配置。有了它，"装引擎 + 指向我的 YAML" 才成立。chunk 1 之后的所有包化工作都建立在这个抽象上。

---

## 4. chunk 1 已交付（本 session）

1. **engine.py**: `_resolve_config_dir()` + `ONTOLOGY_CONFIG_DIR` env 注入（模块级 `_ONTOLOGY_FILE` 等通过它解析）。向后兼容（默认 = 当前 ontology/）。
2. **governance_checker.py**: `_resolve_config_dir()` + `_resolve_project_root()` + `ONTOLOGY_PROJECT_ROOT` env。`__main__` 块抽出 `main()`（行为不变，cron 仍走 `__main__ → main()`）供 console 入口。
3. **pyproject.toml**: 声明 `openclaw-ontology-engine` 0.1.0，`packages=["ontology"]`，`package-data` 含 YAML + CONSTITUTION.md，console_scripts `openclaw-ontology-audit` / `openclaw-ontology-query`。`pip install -e .` 后 `import ontology` 工作。
4. **本文档** + `test_ontology_packaging.py`（注入单测 + 反向验证）。
5. **验证**: full_regression 0 fail + governance 全绿 + **删除 ontology 后 proxy FAIL-OPEN 正常**（宪法第一条）。

---

## 5. 已知耦合（诚实登记，迁移时处理）

| 耦合 | 位置 | 性质 | 处理 |
|---|---|---|---|
| `from proxy_filters import ALLOWED_TOOLS,...` | `engine.py::main()` 的一致性 diff CLI | **lazy + try-guarded**，仅 CLI `--diff` 功能用，核心引擎不依赖 | 包内 `--diff` 无 proxy_filters 时 try 失败优雅降级；属 Layer 2 消费方耦合，记录即可 |
| `import convergence` / `from ontology import convergence` | `governance_checker.py::run_convergence_specs()` | convergence 是 `ontology` 子模块，双 fallback 已 package-aware | `packages=["ontology"]` 自动含，无需处理 |
| ~~**convergence spec 路径不读 `ONTOLOGY_CONFIG_DIR`**~~ ✅ **V37.9.107 chunk-3a 已修复** | `convergence.py` 现有 `_resolve_config_dir()` + `_resolve_project_root()`（镜像 engine.py / governance_checker.py） | **chunk-4 demo 暴露 → chunk-3a 闭环**：convergence 现读 `ONTOLOGY_CONFIG_DIR` 的 spec + 经 `ONTOLOGY_PROJECT_ROOT` 解析源文件（jobs_registry.yaml / *.json）。无 env 时默认分支保持 V37.9.19 `.resolve()` 语义字节级不变（零回归）。 | ✅ 已修。demo 新增 `convergence_ontology.yaml` + `weatherbot_state.json`，run_demo.py section 5 端到端验证（消费方读自己 spec 非 bridge）。14 新单测 + 反向 sabotage 守卫 |
| ~~MRD 扫描文件名/glob 模式 (`jobs_registry.yaml` / `notify.sh` / `preflight_check.sh` / 诊断白名单 / 7 glob 形状 / push-route 白名单)~~ ✅ **V37.9.126 chunk-3b + V37.9.127 chunk-3b.2 全修复** | `governance_checker.py::_discover_*()` | **全部 MRD 扫描模式已 config-inject**：`_load_mrd_patterns()` 读 `governance_ontology.yaml::mrd_scan_patterns` (单文件 chunk-3b + 7 glob-set + push-route 白名单 chunk-3b.2)，`_mrd_globs()` helper；消费方可 override 自己的项目结构 (如 `skills/**/*.py`)；缺段/键 → `_MRD_DEFAULTS` (bridge 字节级一致)。WeatherBot demo 端到端验证 (`weatherbot_jobs.yaml` + `skills/**/*.py`)。 | ✅ 全修。byte-identical 验证 (89 inv/14 MRD discovery + 12 glob-依赖计数全不变) + 40 单测 + 反向 sabotage + demo。MRD 扫描器全部项目无关化 (终极目标可包化粒度达成)。 |
| `governance_ontology.yaml` 的 python_assert 引用项目文件 | Layer 2 配置内 | 本就是 Layer 2（项目特定不变式） | 无需处理，消费方写自己的 |

---

## 6. 迁移路标

| chunk | 内容 | 风险 | 状态 |
|---|---|---|---|
| **1** | config-injection keystone + pyproject + 二层契约文档 + 包结构 | 低（向后兼容） | ✅ 完成 (V37.9.99-pkg) |
| **4 (本次)** | Extension Guide + 最小可跑 demo (WeatherBot 消费方) + config-injection 端到端验证 + 端到端测试 | 低（纯新增） | ✅ 完成 (V37.9.104) |
| 2 | ✅ **V37.9.128 chunk-2-lite 完成**：import 名去泛化 `ontology` → **`ontology_engine`** 经 pyproject `package-dir = {ontology_engine = "ontology"}` 映射 (零目录 rename / 零内部 churn / 零 Mac Mini symlink 变动)。消费方 `pip install openclaw-ontology-engine` → `import ontology_engine`; bridge dev 双名共存 (`import ontology` 本地 + `ontology_engine` 经映射)。内部 `from ontology import convergence` 已双模式 flat fallback → 装成 ontology_engine 仍工作 (从 /tmp 消费方场景跑 governance audit + convergence specs 验证)。console 入口 `ontology_engine.X:main`. **用户决策选低风险方案** (勘察发现完整 dir rename 是 50+ 文件, `ontology` 重载为概念词需逐处判断, 价值偏思辨无实际冲突). 4 断言更新 + 3 behavioral (映射/子模块/本地向后兼容). | 低（映射, 非破坏性目录 rename） | ✅ 已完成 (lite) |
| **3a (本次)** | **convergence config-injection**：`convergence.py` 加 `_resolve_config_dir()` + `_resolve_project_root()`，spec 路径 + 源文件根（6 src_path + json + 2 sys.path）全经 env 注入。demo 加 `convergence_ontology.yaml` + `weatherbot_state.json` + run_demo.py section 5 端到端验证 | 低（向后兼容，默认 `.resolve()` 字节级不变） | ✅ 完成 (V37.9.107) — chunk-4 demo 暴露的耦合闭环 |
| 3b | ✅ **V37.9.126 完成 (单文件部分)**：MRD 扫描**单文件名** (`registry_file`/`notify_file`/`preflight_file`/诊断白名单) 移到 Layer 2 `mrd_scan_patterns`；`_load_mrd_patterns()` + `_MRD` 模块常量 + FAIL-OPEN observable except。byte-identical (89 inv/MRD discovery 不变) + 24 单测 + demo `weatherbot_jobs.yaml` 端到端注入。 | 中（触碰 MR-4 血案防护扫描器，已 byte-identical 验证） | ✅ 已完成 (单文件) |
| 3b.2 | ✅ **V37.9.127 完成**：per-scanner **glob 形状**参数化 — 7 glob-set 键 (`topic_scan_globs`/`channel_source_globs`/`repo_shell_globs`/`alert_monitor_globs`/`llm_caller_globs`/`llm_caller_py_globs`/`py_scan_globs`) + `push_route_whitelist` 移到 `mrd_scan_patterns`。`_mrd_globs(key)` helper (统一 `recursive=True` — 对非 `**` 模式 no-op 对 `**` 必需，保留各扫描器 set/extend/sorted 累积语义)。byte-identical 验证 (12 个 glob-依赖计数 48 shell/41 non-whitelist/72 .py/46 LLM/5 topics/82 silent-error/2 monitor 全不变 + 89 inv) + 16 单测 + demo `skills/**/*.py` 端到端注入。 | 中-高（已 byte-identical 验证消除回归风险） | ✅ 已完成 |
| 5 (Phase 5 终态) | 真 sdist/wheel 构建 + `pip install` (非 editable) 冒烟 + 发布决策 (PyPI 名 / license / readme) + 版本治理 (semver) + 第三方项目接入验证 | — | 待启动 |

---

## 6.1 推荐推进顺序（专业建议）

> **不按数字顺序推，按"先证明价值、再做破坏性投入"推。**
> 推荐顺序：**chunk 4 → chunk 3a → chunk 2 → chunk 3b → chunk 5**
> （V37.9.107 调整：chunk 3a（convergence config-injection）是 demo 暴露的低风险真 bug 且 de-risk chunk 2（更少东西硬编码到 `ontology/` 目录），提前到 chunk 2 之前做。）

| 顺位 | chunk | 为什么这个位置 |
|---|---|---|
| **① 先做** ✅ **V37.9.104 完成** | **chunk 4** Extension Guide + 最小可跑 demo | **风险最低（纯新增，不改现有代码），价值最直观。** 第一次有"第二个项目"真用引擎 → 端到端验证 config-injection + 四大能力（工具查询/域查询/策略评估/治理审计）。这是引擎的 **"Doubao 时刻"**：Provider Plugin 直到 Doubao（第 8 个 provider，V37.9.52）真接入才被证明可扩展；引擎同样需要一个真实消费方 demo 来证明抽象正确。**交付**: `examples/minimal_consumer/` (WeatherBot — 工具/域/策略/不变式全部不同于 bridge) + `run_demo.sh` (端到端跑通) + 12 单测（含反向验证：不注入 env → 引擎读 bridge 配置，证明 demo 通过依赖注入）。**demo 自然暴露 convergence 路径耦合**（§5 新登记），印证 ③ 的预期。demo 用当前 `import ontology`，显式标注"import 名是临时的，chunk 2 会改"。 |
| **② 次之** | **chunk 2** import 名去泛化 | **最高风险（破坏性：proxy lazy-load + Mac Mini symlink + 全部 import + tests），必须全宪法验证**（删除后正常 + full_regression + 删除安全）。放在 ① 之后是因为：demo 已证明能力成立 → rename 退化为"有明确目标的机械重构"。**绝不第一个做**——在没验证价值前先做破坏性重构，是把风险放在收益前面。 |
| **② 次之** ✅ **V37.9.107 完成** | **chunk 3a** convergence config-injection | demo（①）真实暴露的耦合（convergence 是 demo 唯一规避的阶段）。低风险（向后兼容）、纯 dev、无需定包名/symlink。提前到 chunk 2 之前做因为它 **de-risk chunk 2**：convergence 不再硬编码到 `ontology/` 目录，rename 时更少东西要改。**交付**: `convergence.py` 两 resolver + demo `convergence_ontology.yaml`/`weatherbot_state.json` + run_demo.py section 5 + 14 单测 + 反向 sabotage 守卫。 |
| **③ 第三** | **chunk 2** import 名去泛化 → **chunk 3b** MRD 模式参数化 | chunk 2 仍是最高风险破坏性 rename（见 ② 原 chunk 2 段，需定包名 + Mac Mini symlink + 全宪法验证）。chunk 3b（MRD 文件名模式 → Layer 2）放最后因为它触碰 ~10 个 MR-4 血案防护扫描器，需聚焦 session，且当前已优雅 no-op（非紧急）。 |
| **④ 最后** ✅ **V37.9.133 完成 (publish-ready)** | **chunk 5** 发布就绪 | sdist (325KB) + wheel (312KB) `python3 -m build` 首次真实构建成功；/tmp venv 从 wheel 安装冒烟（import ontology_engine + 全子模块 + bundled 默认 16 tools）；WeatherBot config-injection 注入消费方 YAML 零 bridge 泄漏；venv `bin/openclaw-ontology-audit` 真跑 WeatherBot 治理审计 exit=0（含 convergence spec）。pyproject 补 `license = {file = LICENSE}` (MIT) + `readme = PACKAGE_README.md`（英文包级 README，PyPI 门面）+ classifiers。`.gitignore` 加 dist/ + *.egg-info/。**实际 PyPI 上传 = 用户决策**（需 PyPI 账号/token + 分发名最终确认，见 §7.2）。 |

**核心工程智慧**：先用便宜的 spike/demo 验证整个包化前提，再投入昂贵的破坏性重构——如果 demo 暴露抽象有问题，就避免了白做 chunk 2 的破坏性 rename。这与本项目 **原则 #18（补证据而非补功能）** + **Provider Plugin 由真消费方（V37.9.52 Doubao）驱动** 一脉相承：扩展接口的价值，只有真实消费方接入那一刻才被证明。

---

## 7. 开放决策（发布前必答）

1. **import 名**: ✅ **V37.9.128 chunk-2-lite 已定 = `ontology_engine`**（经 pyproject `package-dir` 映射，非目录 rename）。原 chunk-2 完整 dir rename 方案勘察发现是 50+ 文件破坏性重构（`ontology` 重载为概念词 — keyword 列表 / dict 键 / 子串检查 / 测试数据 / 主题串 — 需逐处人工区分包路径 vs 概念词 + Mac Mini symlink broken-window），价值偏思辨（无实际消费方名冲突）。**用户选低风险 package-dir 映射**：消费方导出名 = `ontology_engine`，bridge 内部零改动（`import ontology`/symlink/proxy lazy-load 全不动），内部自引用已双模式 flat fallback 故 package-name-agnostic。去泛化目标达成，零破坏性。
2. **分发名**: `ontology-engine` 0.1.0 公共 PyPI 已被他人占用（status.json 已登记撞名）。chunk 1 用 `openclaw-ontology-engine`。是否申请 scoped / 改名 = 发布时决定。
3. **license**: ✅ **V37.9.133 已定 = MIT**（LICENSE 文件已在仓库根，pyproject `license = {file = "LICENSE"}`，wheel 的 dist-info/licenses/ 已验证包含）。
4. **readme**: ✅ **V37.9.133 已建 = `PACKAGE_README.md`**（英文包级 README：两层架构 + quick start + 5 capabilities + WeatherBot 链接，METADATA Description-Content-Type: text/markdown 已验证）。剩余唯一开放决策 = **实际 PyPI 上传**（用户提供 PyPI 账号/token，见 §7.2 runbook）。

### 7.2 上传 runbook — ✅ **已发布（2026-06-11, V37.9.137）**

> **🎉 `openclaw-ontology-engine 0.1.0` 已正式发布**: https://pypi.org/project/openclaw-ontology-engine/0.1.0/
> 用户 Mac Mini 按本 runbook 执行（dev 容器 upload.pypi.org 不在网络 allowlist，twine 403 "Host not in allowlist"）。
> 发布后三层冒烟（dev 容器从真 PyPI 验证）: ① JSON API 200（name/version/MIT/2 files）② 干净 venv
> `pip install openclaw-ontology-engine` → import ontology_engine + engine/governance_checker/convergence
> 全子模块 + bundled 16 tools + 2 console scripts ③ **WeatherBot config-injection 经 PyPI 包真跑
> `openclaw-ontology-audit` exit=0 + convergence 零 drift** — pip install → 消费方 YAML → 审计自己的项目，
> V3 路标终极闭环（这次是公开 PyPI 包而非本地 wheel）。
> 发布用 account-scoped token 已要求用户撤销（用完即弃）；未来发版用 project-scoped token。
> **未来发版流程**: bump pyproject `version` → 本 runbook 4 条命令。已知低优 follow-up: setuptools
> 警告 `project.license` TOML table 形式 2027-02 起 deprecated（届时改 SPDX 字符串 `license = "MIT"`）。

#### 原 runbook（保留供未来发版）

**2026-06-11 实证状态**：
- ✅ `python3 -m build` 构建通过（sdist 326KB + wheel 313KB）
- ✅ `twine check dist/*` 双 PASSED — **注意环境陷阱**：系统 `packaging < 24.2` 时 twine 误报
  `unrecognized field 'license-file'`（Metadata-Version 2.4 的 License-File 字段需 packaging ≥ 24.2
  才能解析；dev 容器 debian packaging 24.0 复现此假阳性）。**必须用 venv twine**（见下方命令）。
- ✅ **分发名 `openclaw-ontology-engine` 在 PyPI 可用**（2026-06-11 实证：
  `pypi.org/pypi/openclaw-ontology-engine/json` → 404；对照 `ontology-engine` → 200 已被占）。

**上传命令（用户拿到 PyPI API token 后，任意机器 ~30 秒）**：

```bash
cd ~/openclaw-model-bridge
python3 -m venv /tmp/pub_venv && /tmp/pub_venv/bin/pip install -q build twine
/tmp/pub_venv/bin/python -m build                      # 重新构建 (dist/ 不入库)
/tmp/pub_venv/bin/twine check dist/*                   # 必须双 PASSED
/tmp/pub_venv/bin/twine upload dist/* \
  -u __token__ -p "pypi-<YOUR_API_TOKEN>"              # token 从 pypi.org/manage/account/token 创建
# 验证: pip install openclaw-ontology-engine 应立即可装
```

可选先传 TestPyPI 演练：`twine upload --repository testpypi dist/*`（token 从 test.pypi.org 单独创建）。

---

## 8. 向后兼容 & 宪法（删除后原系统正常）

chunk 1 **零破坏**：
- 无 env 时所有路径解析 = 当前行为（`dirname(__file__)`），Mac Mini / dev / cron 行为不变。
- `proxy_filters.py` 仍 lazy-load `ontology/engine.py`（`spec_from_file_location`），env 未设 → 默认 → 正常；**删除整个 `ontology/` → proxy FAIL-OPEN 回退 config**（宪法第一条，chunk 1 未触碰此机制）。
- `governance_audit_cron.sh` 仍 `cd repo && python3 ontology/governance_checker.py --full` → `__main__ → main()` → 行为不变。
- `pyproject.toml` 是**新增**文件，不被任何现有运行时读取（仅 `pip install` 时用），对生产零影响。

---

## 9. 用法

### 本仓库内（chunk 1 已可用）

```bash
pip install -e .                              # editable, import ontology 指向 ontology/
openclaw-ontology-audit                       # = python3 ontology/governance_checker.py
ONTOLOGY_CONFIG_DIR=/other/cfg openclaw-ontology-query --json   # 引擎指向别处 YAML
```

### 未来消费方（chunk 4 Extension Guide 完整化后）

```bash
pip install openclaw-ontology-engine
mkdir myproject/ontology && cp <templates> myproject/ontology/
export ONTOLOGY_CONFIG_DIR=$PWD/myproject/ontology
export ONTOLOGY_PROJECT_ROOT=$PWD/myproject
openclaw-ontology-audit                       # 审计 myproject 的不变式
```

---

## 参考

- `ontology/CONSTITUTION.md` — Ontology 宪法（最高条款：删除后原系统正常）
- `ontology/engine.py` / `governance_checker.py` — Layer 1 引擎
- `docs/provider_plugin_guide.md` — Provider Plugin 模式（chunk 4 Extension Guide 的镜像模板）
- `docs/strategic_review_20260403.md` — V3 路标"别人会扩展"
- `docs/articles/ai_partnership_first_principles_zh.md` — control plane = 边界系统的第一性原理
