WorkBuddy 用户级技能源码解析

OKF 知识库生成技能 · 工作原理与使用指南

把任意代码仓库 / 数据集 / 系统通读一遍,沉淀成一份符合 Open Knowledge Format v0.2 规范的知识库 bundle:带 YAML frontmatter 的 markdown 概念文档树、论断级脚注归因、可程序化校验、可渲染成单文件交互知识图谱。本文基于对 okf-knowledge-base 全部源码的逐行研读,并用真实项目跑通了全流程。

仓库 wang-junjian/okf-knowledge-base 形态 1 份 SKILL.md + 2 个独立 Python 脚本 校验器 仅标准库 渲染器 仅需 pyyaml 网络 全程离线 许可 MIT + Apache 2.0(内置上游)
OKF 知识库生成技能一页速览
图 1技能一页速览:左侧是它解决的问题,中间是 v0.2 规范要点与六步生成工作流,右侧是脚本原理与使用指南。图中「3. 脚本原理 & 链接规范化补丁」一节即本文第 4 章,本文在这一页的基础上补齐了源码级细节与实测数据。

01它解决什么问题

一句话:把「代码仓库 / 数据集 / 系统」变成一堆普通的 Markdown 文件,让人和 Agent 用完全相同的方式生产、审查、消费它。技能本体不发明格式,而是严格实现上游 GoogleCloudPlatform/open-knowledge-format 的 v0.2 规范。

痛点OKF 的回答实现锚点
知识只存在于脑子里 / 一次对话里固化成一堆 .md,天然进 git:PR、逐行 diff、blame、评审流程全部免费获得一个概念 = 一个 .md 文件(SPEC §3)
Agent 不理解仓库,只能靠现场 grepfrontmatter 放可查询的少数字段,正文放人和 LLM 真正读的散文 / 表格 / 代码结构化与非结构化刻意混合(SPEC §4)
不知道这条知识可不可信、还新不新鲜来源、信任、生命周期都是可查询的一等公民,而不是靠印象sources[] / verified / stale_after(SPEC §5)
无法分辨「人写的」还是「Agent 编的」Agent 产出一律停在 unverified,人工确认后才能升级只有 human: 前缀能升到 human-reviewed(SPEC §5.3)
平台锁定,换工具就搬不动bundle 就是一个普通目录:tar 包 / 静态服务器 / Obsidian / MkDocs 都能直接用bundle = directory(SPEC §3)
把整个仓库塞进上下文,成本爆炸自动生成的 index.md 让 Agent 逐层浏览、按需加载渐进披露(SPEC §8)

1.1为什么是 Markdown,而不是元数据服务

readable

人和 Agent 读同一份

cat 一下就能看;LLM 可以原样塞进上下文。不存在「给人看的界面」和「给机器读的 API」两套真相。

git-native

知识运营 = 软件工程

PR 评审、逐行 diff、blame、CI 校验,全部复用现成流程,不需要另建知识管理平台。

portable

零锁定

bundle 就是个目录。tar 包分发、静态服务器托管、用 Obsidian / Notion / MkDocs / Hugo 原生浏览都可以。

progressive

渐进披露

index.md 是目录,概念文档是按需加载的单元。Agent 不会一上来就被整个知识库淹没。

技能本身的三条设计底线
  • 不伪造权威性:Agent 生成的内容不写 verified,如实保持 unverified。
  • 编造比缺失更糟:宁缺毋滥,宁可少写一篇,也不写没有源码依据的参数。
  • 不重复目录结构:知识库的价值在「非显而易见的事实」,不是把 ls -R 翻译成中文。

02OKF v0.2 规范要点

生成方必须遵守的部分。规范全文内置在 references/SPEC.md(1014 行,上游 commit 0b87c52 快照),SKILL.md 只是流程提炼——两者冲突时以 SPEC 为准。

okf/ —— 一个 bundle 就是一个普通目录 分发形式:git 仓库(推荐)· tar/zip · 或大仓库的子目录 okf/ ├─ index.md ← 唯一可带 frontmatter:okf_version: "0.2" ├─ log.md ← ISO 日期分组,newest first ├─ overview/ ← 产品全景 / 架构总览(1~3 篇) ├─ <领域分区>/ ← core · systems · entities · ui … │ └─ index.md ← 无 frontmatter,纯导航 ├─ playbooks/ ← 构建 / 调试 / 发布手册 ├─ references/ ← 清单、CI、资产 └─ viz.html ← (可选)单文件交互图谱 三条硬约定 ① 保留文件名只有 index.md / log.md 不能拿来当概念文档;任何「切 --- 取第 2 段」的解析必须跳过它们 ② 一个概念 = 一个 .md;目录按领域自由组织 目录树只是骨架,分区怎么切由领域决定,不硬套模板 ③ 链接构成有向图,可跨目录 关系类型(depends-on / joins-with…)由周围散文表达,链接本身不带类型 A B C D 边 = 反向链接的来源, 被指最多的节点 = 架构核心
图 Abundle 的目录骨架与三条硬约定。注意 index.md / log.md 是唯二的保留名,二者本身不算「概念」——这一点在渲染阶段会造成一个直观差异(见 6.4)。

2.1概念文档:唯一必填字段是 type

只带 type 的概念即完全合规。其余字段分为四个家族,全部可选,但推荐填满前两个家族。

家族字段必填说明
结构type必填全局唯一必填项。用自解释英文 token(Module / Component / Playbook / Config / Reference / Concept / State Machine…);消费者对未知 type 按通用概念处理
title / description推荐description 会被 index.md 与搜索摘要原样引用,保持一句话
resource推荐指向概念描述的底层资产(源文件路径 / URL);纯抽象概念可省
tags可选YAML list,用于跨分区归类与前端搜索
溯源sources[]实质必填正文有脚注则必填。每条含 id(脚注 join key)、resource(必填)、title;id 用稳定标识而非位置索引,因为 Agent 会不断重写文档,列表重排会让 sources[0] 静默错配
信任generated推荐{ by, at };by 遵循 actor 约定
verified不伪造Agent 生成且未人工确认时不要写。写了就等于伪造权威性
生命周期status可选draft / stable(缺省)/ deprecated;反映现有代码的写 stable,推断/未证实内容写 draft
stale_after可选绝对时刻,now >= stale_after 即过期
unverified frontmatter 里没有 verified 键 = Agent 产出的默认态,也是本技能 任何输出所处的状态 machine-confirmed verified 只被 process:<id> / 工具确认 = 机器表示「我核对过」,但没有人 为内容正确性背书 human-reviewed verified 里出现 human:<id> = 格式设计上无法伪造的「人工已核对」 状态,PR 里谁升级的、什么时候,都是数据 actor 命名约定(generated.by / verified[].by 通用) <producer>/<version> Agent / 工具 例:workbuddy/glm-5.3-flash human:<id> 人 ← 只有它能升级 trust tier process:<id> 自动流程 OKF 只记录客观信号,不记录主观评分
图 B信任层由 verified 推导,判定权在前缀:human: 之外的任何 actor 都只能到 machine-confirmed。渲染时这一层会变成节点详情面板上的彩色 badge。

2.2链接的两种写法:本技能选了「仓库根基准」

规范允许两种绝对/相对写法。本技能内部约定了一套看似矛盾、实则有明确理由的组合——这是理解后续所有「链接错位」问题的前提:

位置本技能的写法为什么
正文里的概念互链[事件总线](/okf/core/event-bus.md)
仓库根基准,带 /okf/ 前缀
编辑器 / 查看器以仓库根解析绝对路径,旧写法 /core/x.md(bundle 根基准)会指向不存在的位置
正文里的源码脚注[^main-src]: /src/main.ts
同样是仓库根基准
脚注归因行最终渲染成正文文本,路径基准与正文一致才不会点歪
frontmatter 的 resourceresource: ../../src/core/Game.ts
文档相对,不用 / 开头
渲染器对 frontmatter 里 / 开头的值原样放行,会按 bundle 根解析而跳错位置;文档相对写法则由规范化补丁自动处理
记忆口诀

正文用仓库根(/okf/…),frontmatter 用文档相对(../../…)。两者都符合规范;之所以要分开,是因为渲染器对这两个位置的 / 开头路径处理策略不同——正文会被 rewire 成图内跳转,frontmatter 则原样当链接。

2.3两条容易被忽略的规范精神

SPEC §11 · 消费者侧

断链是合法状态

消费者 MUST NOT 因断链拒绝 bundle——断链可能只是「尚未写出的知识」。这直接决定了本技能的定位:校验脚本是生成方 lint,在发布前把断链当硬失败拦住,而不是伪装成合规检查。

SPEC §11 · 兼容性

宽容是规范的一部分

type 值不注册、消费者必须容忍未知类型与未知键;缺任何一个可选字段家族都不能被拒绝。所以写知识库时不需要「先对齐 type 词表」,自由扩展是允许的。

03六步生成工作流

SKILL.md 定义的执行路径。第 4 步校验是必做项,第 6 步渲染按需触发。

① 项目侦察 README · package.json · CI find + wc -l 估规模 → 通读/抽样 ② 设计分区 overview / <领域> / playbooks 每分区一个 index.md ③ 生成概念文档 frontmatter + 正文 40~90 行 互链 + per-claim 脚注归因 ④ 校验(必做) validate_okf.py 非 0 退出即不通过 ⑤ 交付 root index.md 作入口 + 分区统计表 + 信任状态说明 ⑥ 渲染图谱(可选) render_viz.py 触发词:知识图谱 / viz / 可视化
图 C①→④ 是主干,④ 是硬闸门;⑤ 交付与 ⑥ 渲染图谱是 ④ 之后的两条出口。渲染是独立支线,可反复重跑而不影响 bundle 源文档。

3.1第 1 步 · 项目侦察:读什么、怎么收敛

  • 先读 README.md、构建清单(package.json / pyproject.toml / Package.swift)、CI 配置、关键脚本。
  • 列出全部源文件并看规模(find … -type f + wc -l):≤50 个源文件时全部通读;更大的仓库按模块分层抽样,但每个模块至少精读核心文件。
  • 边读边记「非显而易见的事实」——这是知识库价值的全部来源:真实参数(速度 / 时长 / 阈值 / 权重)、设计取舍的注释、实现注记(「原用 Picker 但不生效,换成按钮」)、模块间联动链。
  • 反模式:把目录结构翻译成中文、复述类名和方法名。这类内容占篇幅但不增加信息。

3.2第 2 步 · 设计分区

okf/
  index.md          # okf_version: "0.2"(全 bundle 唯一允许带 frontmatter 的 index)
  log.md            # ISO 日期分组、newest first
  overview/         # 产品全景、架构总览、核心机制(1~3 篇)
  <领域分区>/        # 按模块拆:core/ pet/ controllers/ views/ api/ ...
  playbooks/        # 构建 / 调试 / 发布的操作手册
  references/       # 清单文件、CI、资产等次级材料

每个分区写一个 index.md(无 frontmatter,按分区分组列链接 + 一句话描述)。

「每分区必有 index」是本技能的约定,不是规范要求

SPEC §11 明确:分区 index 缺失不构成拒绝理由。validate_okf.py 也只检查 root index.md 的 okf_version。这条约定存在的唯一目的是保证导航完整性——你若手工维护 bundle,可以不放。

3.3第 3 步 · 生成概念文档

---
type: Module            # 必填;自解释英文 token
title: 中文名(或项目语言对应的标题)
description: 一句话概括
resource: ../../Sources/...   # 文档相对路径;勿用 / 开头
tags: [a, b]
generated: { by: workbuddy/glm-5.3-flash, at: 2026-09-16T22:05:00+08:00 }   # ISO 8601 带 UTC 偏移
sources:
  - id: game-src        # 正文脚注 [^game-src] 与此 id 逐字对应
    resource: ../../src/core/Game.ts
    title: src/core/Game.ts
status: stable          # 反映现有代码的写 stable;推断/未证实内容写 draft
---
正文规则要求
结构化优先表格列参数、fenced code 列关键代码;保留真实数字(300px/s、25 分钟、30% 概率)
篇幅每篇 40~90 行为宜,聚焦「这个模块是什么、怎么工作、和谁联动」
互链联动对象用仓库根基准绝对链接:[事件总线](/okf/core/event-bus.md)
归因每处具体论断后标脚注 [^id],文末给脚注定义行,label 必须与 sources[].id 一致
信任不加 verified 字段——如实保持 unverified
节奏每分区写完立即写该分区 index.md,不要最后补

3.4第 4 步 · 校验(硬闸门)

python3 <skill-dir>/scripts/validate_okf.py <project>/okf

退出码非 0 即不通过。断链先修复再复验,直到全绿——出现过「编辑报成功但落盘未生效」,必须跑绿才算完成。校验器细节见 4.1。

3.5第 5 步 · 交付

把 root index.md 作为入口展示给用户(支持文件预览的环境直接开预览,否则给绝对路径),后跟 2~3 篇核心概念(如架构总览、核心状态机),再附 log.md;最终回复给出分区统计表与信任状态说明。

3.6第 6 步 · 渲染交互式知识图谱(可选)

python3 <skill-dir>/scripts/render_viz.py <project>/okf --name "知识图谱"

产出写到 <project>/okf/viz.html:力导向图 + 详情面板 + 反向链接 + 搜索 / 类型过滤,完全离线可用。渲染后建议做多重验证(bodies 无残留相对链接、resource 均为 bundle 根相对形态、脚注路径已改写、无外部 <script src> / <link href>),并把 concepts / edges 数写进最终回复。原理见 4.3。

04脚本内部机制

技能的全部「可执行部分」约 750 行 Python + 一个内置 viewer 副本。下面按真实调用顺序拆开看。

文件行数职责依赖
scripts/validate_okf.py140bundle 一致性校验(生成方 lint)仅标准库(有 pyyaml 则增强)
scripts/render_viz.py61命令行壳:解析参数、导入内置 viewer、打印统计pyyaml
scripts/okf_viewer/__init__.py24包入口,导出 generate_visualizationpyyaml
scripts/okf_viewer/document.py154frontmatter 解析 / 信任层推导 / 时效判定pyyaml
scripts/okf_viewer/generator.py368遍历 bundle、链接规范化、组图、吐出自包含 HTMLpyyaml
scripts/okf_viewer/templates/viz.html90HTML 骨架,6 个占位符待替换—
scripts/okf_viewer/static/viz.js / viz.css333 / 180前端:cytotscape 实例、搜索、过滤、详情、反向链接cytoscape + marked
static/vendor/cytoscape.min.js
static/vendor/marked.min.js
—内联进产物的第三方库(3.28.1 MIT / 12.0.0 MIT)—

4.1校验器 validate_okf.py

定位很关键:SPEC §11 规定消费者不得因断链拒绝 bundle,而本脚本是生成方 lint——在产出流程里把问题拦在发布前,因此断链按硬失败处理。这不是与规范冲突,而是站在规范的另一侧。

① 输入与预处理 os.walk(root) 排序遍历 *.md 先校验目录存在 + root/index.md 存在 strip_code_blocks(text) 正则去掉 ``` 代码块,防示例文本误报 区分 RESERVED = {index.md, log.md} 保留文件跳过 frontmatter 检查,但不算「概念」 ② 四类检查(全部在去码块文本上做) frontmatter + type 非保留文件必须有可解析 frontmatter 且 type 非空;pyyaml 在时深校验 YAML 链接完整性 正文 .md 链接(含 #锚点) / 开头双基准:bundle 根 / 仓库根 脚注归因双向 每个脚注定义 ↔ 某个 sources[].id 每个 [^id] 引用 ↔ 有脚注定义 root index 版本 root index.md 若带 frontmatter 则必须含 okf_version(§12) 汇总 all errors[] —— 空则通过,非空逐条打印;用法错误(参数个数不对)退出码 2,目录无效 / 有问题退出码 1 ✓ exit 0 · 校验通过 打印「概念文档 N 篇,内部链接 M 条」+ 一行通过说明 ✗ exit 1 · 逐条列出问题 [断链] / [缺 type] / [脚注无对应 sources id] / [脚注引用无定义] …
图 D校验器的完整数据流。所有检查都跑在去掉代码块之后的文本上——这是最容易漏掉的一处实现细节:概念文档正文里常常含 [^x]: … 的示例,不去码块就会被当成真正的脚注定义而误报。

实测输出(tower-defense bundle,pyyaml 有无两种解释器结果一致)

python3 scripts/validate_okf.py okf
bundle: /private/tmp/tdcase/okf
概念文档 21 篇,内部链接 50 条
✓ 校验通过:frontmatter type / 链接完整性(含锚点)/ 脚注归因 全部一致
exit=0
「21 篇 / 50 条」和「22 个节点 / 8 条边」为什么对不上?

这不是 bug,是两套口径:

  • 21 篇:31 个 .md 里,9 个分区 index.md + 1 个 log.md 属保留名被跳过 → 剩 21 篇概念文档。而渲染器只跳过 index.md(不跳 log.md),所以图上是 22 个节点(另见 6.4)。
  • 50 条内部链接:其中 42 条来自 index 的导航链接(root index 21 条 + 8 个分区 index 21 条),index 不是节点,这些不成边;剩下 8 条恰好是概念文档之间的互链 = 图谱的 8 条边。
pyyaml 缺失时的静默降级

校验器会用 try/except ImportError 兜住:没装 pyyaml 时 yaml_ok() 恒返回 True,即跳过 YAML 可解析性深度校验,仍能用正则查 ^type:,保证零依赖可用。渲染器则相反——缺 pyyaml 直接 fail() 退出,因为它真的需要解析 frontmatter。

4.2信任与时效的推导:document.py

渲染时的 badge 不是「读一个字段」,而是从 verified 现场推导出来的。三个函数值得单独看:

trust_tier(fm)

信任层

无 verified → unverified;有事件但没有任何 human: 前缀的 actor → machine-confirmed;出现 human:<id> → human-reviewed。判定只看前缀,不看 by 里的其他内容。

normalize_verified(fm)

单元素宽容

单个 { by, at } mapping 与单元素 list 均合法(SPEC §5.2),消费端一律归一化成 list,避免调用方到处判类型。

is_stale(fm)

时效:宁可不报

now >= stale_after 才算过期。两处保守:值里没有 T(纯日期 2026-12-31)直接不算 —— 它在不同时区是不同的时刻;解析出的 datetime 没有时区信息也不算。都是「不肯猜」的设计。

一个容易被忽略的细节:摘掉 YAML 1.1 的 timestamp resolver

PyYAML 实现的是 YAML 1.1,其隐式解析器会把 2026-06-30T14:00:00Z 解成 datetime 对象;一旦回写就变成 2026-06-30 14:00:00+00:00——一次 parse → serialize 往返就静默改写了作者写的 frontmatter。内置 viewer 用自定义 _Loader 删除了 tag:yaml.org,2002:timestamp 解析器,让所有值保持字符串,与 YAML 1.2 core schema 对齐。

4.3渲染管线:render_viz.py + 内置 okf_viewer

为什么不用官方 python -m reference_agent visualize

官方 CLI 的顶层 import 会拉起 google.adk / google-cloud-bigquery 等几个 GB 的重依赖,而渲染链路实际只需要 pyyaml。内置的 okf_viewer 包就是从上游 viewer 提取出的独立副本(Apache 2.0,含链接规范化补丁),直接调用,效果与 CLI 完全一致,且无需 clone 上游仓库。

① _walk_concepts(bundle_root) → list[Concept] rglob("*.md") 排序遍历 跳过 index.md(log.md 不跳过) concept_id = 相对路径去掉 .md OKFDocument.parse() 切 frontmatter / body,失败即跳过 tags / sources 做类型宽容归一 四处链接规范化 _normalize_body_links _normalize_resource / 脚注改写 Concept(...) trust_tier / stale / sources links_to = _extract_links(body) ② _build_graph(concepts) → graph dict 建边:跳过自环、跳过指向不存在节点的目标、同向重复边去重 target not in ids → 静默丢弃(这就是链接写错时图谱变稀的原因) graph = { nodes, edges, bodies, types, palette } data:label · type · resource · tags · status · verified · trust_tier … ③ generate_visualization() → 单文件 viz.html 模板 6 处字符串替换 /*__VENDOR_CYTOSCAPE__*/ /*__VENDOR_MARKED__*/ /*__VIZ_CSS__*/ /*__VIZ_JS__*/ __BUNDLE_NAME__ __BUNDLE_DATA__(json.dumps 内嵌) 内联前的防御处理 _load_vendor_js() 把 "</script" 转义为 "<\/script" (JSON 字符串里 \/ === /,语义不变;防止第三方库提前闭合宿主标签) 返回统计 {concepts, edges, bytes} 供命令行打印
图 E渲染三段式:走文件 → 组图 → 灌模板。整个产物零外部引用:cytoscape 与 marked 已内联,代价是体积 +约 400 KB。

节点尺寸与配色是怎么定的

属性公式 / 取值含义
节点直径30 + min(60, len(body) // 200)30~90 px,与正文长度正相关——越大 = 写得越详细
节点颜色调色板仅定义 3 种 type:BigQuery Dataset #8b5cf6 · BigQuery Table #3b82f6 · Reference #10b981其余一切 type 走默认 #94a3b8 灰。见 6.3 的实测发现
过期标记node[?stale] → 红色虚线边框加粗由 stale_after 推导
废弃标记node[status="deprecated"] → 透明度 0.55保留在图上但视觉降权
选中态琥珀色 3px 边框(节点 / 边)点击节点后从图上定位

产物里的前端能力

search

搜索 title / id / tag

命中之外的节点与边统一加 .dim 降到 15% 透明度,而不是隐藏——上下文始终可见。

filter

按 type 过滤

下拉项由 graph.types 动态生成,与调色板无关,所以灰节点依然可筛。

layout

5 种布局切换

cose(力导向,默认)/ concentric / breadthfirst / circle / grid,外加 Reset view。

detail

详情面板

type chip + id + description + resource 链接 + tags + generated/verified + sources 列表 + marked 渲染的正文。

badges

v0.2 信号 badge

status(stable/draft/deprecated)、trust tier、stale 三项,前端按 CSS 类着色。

backlinks

Cited by 反向链接

由边表反查生成,点击即跳转该节点。被引用最多的节点 = 架构核心,这是免费的依赖热度图。

图内跳转是怎么接上的

前端 rewriteInternalLinks() 只处理 / 开头且以 .md 结尾的 <a href>:目标若在 nodeIndex 里,就把 href 改成 javascript:void(0) 并挂上 showDetail(),实现不刷新页面的图内导航;否则降级为外链(target="_blank" rel="noopener")。这就是为什么正文链接必须被规范化成 bundle 绝对形式——否则一律降级成外链,图就「点不动」。

4.4链接规范化补丁:7 节改动清单

这是本技能相对上游 viewer 的全部本地差异,记录在 references/generator-patch.md(同时是给上游提 PR 的素材)。理解它的价值在于:这些症状在写成「文档相对」或「仓库根基准」链接时必然出现,而不是偶发 bug。

#改动解决的症状
1_LINK_RE 升级为带锚点捕获组规范化时 #锚点 被丢掉,跳到文件顶部而非小节
2新增 _normalize_body_links / _normalize_resource正文与 frontmatter 的文档相对路径(../core/x.md、../../src/…)按 bundle 根解析 → 链接整体错位一级
3在 _walk_concepts 的 Concept 构造处接线(body、resource、sources[].resource)规范化函数写了但没接上,等于没改
4_extract_links 支持 / 绝对形式原实现只认文档相对链接,与 SPEC §6.1 推荐的 /x.md 矛盾——官方形态的 bundle 会丢图边
5新增 _repo_root_abs():/okf/分区/x.md → /分区/x.md仓库根基准链接按 bundle 根解析成不存在的 okf/…,边被丢弃、链接降级为外链。带存在性检查,防止分区恰好与 bundle 目录同名时误伤
6新增 _rewrite_footnote_repo_paths():脚注定义行的仓库根路径改写为 bundle 根相对[^main-src]: /src/main.ts 渲染成正文文本后,/ 开头会落到文件系统根(file:///src/main.ts);裸 README.md 则落在 bundle 内不存在的位置
7第三方库内联(/*__VENDOR_*__*/ 占位符 + </script 转义)原模板经 jsdelivr CDN 加载 cytoscape / marked,断网即失效
补丁 6 的一个安全边界

改写只在生成端发生,源 bundle 文档保持仓库根基准写法不动。而且它只匹配脚注定义行 ^(\[\^id\]: )(\S+)$,路径必须「bundle 内不存在、但相对仓库根存在」才改写;两边都不存在就原样保留不瞎猜——宁可能点歪,也不猜一个看似合理的路径。

回归验证方式:官方 bundle(bundles/ga4、bundles/stackoverflow,全用 / 绝对形式)渲染后边数应与仓库里已提交的 viz.html 一致(8 / 54)。补丁对官方 bundle 零影响。

05使用指南

三种用法:让 Agent 走完整工作流、手动跑两个脚本、或把它接进 CI。

5.1安装

# WorkBuddy(用户级技能,全项目可用)
git clone <repo> ~/.workbuddy/skills/okf-knowledge-base

# 其他 Agent 框架:放到你的框架扫描 SKILL.md 的位置即可

技能本体与运行环境无关:一份 SKILL.md 工作流 + 两个独立 Python 脚本。

5.2用法一:对话式(推荐)

你说触发的能力
「按 OKF 标准为本项目生成知识库」六步主干:侦察 → 分区 → 生成 → 校验 → 交付
「生成 OKF 知识库」「OKF knowledge bundle」同上(技能描述里的触发词)
「顺便出一份知识图谱 / 可视化 / viz」追加第 6 步渲染,产出 okf/viz.html

5.3用法二:脚本式

# ① 校验(仅标准库,零依赖)
python3 scripts/validate_okf.py <project>/okf

# ② 渲染交互式知识图谱(需要 pyyaml;渲染器已内置,无需 clone 上游)
python3 scripts/render_viz.py <project>/okf --name "知识图谱"
python3 scripts/render_viz.py <project>/okf --out /tmp/kg.html --name "临时图"
脚本参数默认说明
validate_okf.py<bundle-root>(位置参数)—必须是含 index.md 的目录,否则退出码 1
render_viz.py<bundle-dir>(位置参数)—同上
--out<bundle>/viz.html输出 HTML 路径
--namebundle 目录名查看器标题栏显示名
$ python3 scripts/render_viz.py okf --name "知识图谱"
✓ 22 concepts / 8 edges / 496898 bytes -> /path/to/okf/viz.html
解释器选择提示

两个脚本对 pyyaml 的态度不同:校验器没有也能跑(降级为浅校验),渲染器没有直接报错退出(✗ 当前解释器缺少 pyyaml,请先 pip install pyyaml)。如果你机器上默认 python3 没装 pyyaml,只需给渲染那一步换一个解释器即可,不必改任何代码。

5.4用法三:接进 CI

把「知识库是否自洽」变成一次 PR 检查——这是 OKF 相对知识管理平台最大的工程收益:

# .github/workflows/okf.yml(示例)
- run: python3 scripts/validate_okf.py okf
# 退出码非 0 即 CI 失败:断链 / 缺 type / 脚注归因断裂都拦在合并前

5.5frontmatter 填写速查

模板

最小可用 vs 推荐

最小合规:只有 type。
推荐:type + title + description + resource + tags + generated;正文有脚注则 sources[] 实质必填。

易错点

两处最容易写反

resource 用文档相对(../../src/x.ts),正文互链用仓库根(/okf/…)。反过来写不会立刻报错,但渲染时会链接错位。

id 稳定性

脚注 join key 要用语义 id

用 game-src 而不是 sources[0]——Agent 会不断重写文档,位置索引在列表重排后会静默错配,而 id 不会。

时效

stale_after 要带完整时刻

写 2026-12-31T00:00:00Z;纯日期 2026-12-31 会被刻意忽略(不同时区是不同的时刻,规范不肯猜)。

5.6把信任层用起来:人力确认的完整动作

用户确认某篇内容后,追加一个 verified 即可让它在图谱里从灰转绿:

# okf/core/game.md —— 人工复核后追加这一行
verified: { by: human:wang-junjian, at: 2026-09-17T06:00:00+08:00 }
# 单个 mapping 或单元素 list 都合法;渲染后 badge 变为 human-reviewed

推荐的分工:generated.at 记录「内容什么时候被重新生成」;verified 记录「谁在什么时候确认它仍然正确」。定义过时用 status: deprecated 保留链接与历史,有时效的知识用 stale_after 到时候自动变红。

06实战案例:为「塔塔合成」生成知识库

真实跑通的案例:一款 Vite 5 + 纯 TypeScript(strict)+ HTML5 Canvas 2D 的合成塔防小游戏,零游戏引擎、零音频资源、零运行时依赖。下面所有数字都取自实际产物,不是示意值。

VS Code 中的 okf bundle 目录树与 index.md 预览
图 2交付形态:okf/ 直接躺在项目根目录,右侧是 root index.md 的预览效果。左侧树里 8 个分区(config / core / entities / overview / playbooks / references / systems / ui)各带一个 index.md,底部是 log.md 与 viz.html。观察点:它就是普通 markdown 文件——没有任何插件、数据库或私有格式,编辑器自带的预览就能读。

6.1输入与产出

输入规模
22
个 TypeScript 源文件(约 4600 行)
概念文档
21
篇 + 9 个 index + 1 个 log
图谱节点 / 边
22 / 8
viz.html 渲染出的实际数量
viz.html 体积
488KB
500,005 字节,零外部引用
分区篇数内容
overview/2产品全景与玩法规则 · 架构总览
config/2全局数值配置(平衡调参唯一入口)· 战场地图(MapDef 数据驱动)
core/3Game 主类 · 事件总线(14 个事件清单)· 合成音效
entities/4防御塔 · 敌人 · 弹道 · 粒子系统
systems/4波次管理 · 经济系统 · 强化修饰器 · 强化池
ui/2HUD 与卡池栏 · 指针输入
playbooks/2构建与运行 · 平衡仿真(无头 AI 自动打 20 波)
references/2已知注意点与坑位清单 · 持久化键(localStorage)
合计21 篇概念文档(8 种 type:Component 7 · Module 6 · Config 2 · Playbook 2 · Reference 2 · Concept 1 · Content Library 1 · 另 log 落为 Unknown)

log.md 里记下了这次生成的「非显而易见事实」清单,可以直接看出知识库的价值密度:mergeRefundAmount 是死代码、强化卡描述与实际乘区不一致、localStorage 实际有 3 个键(AGENTS.md 只记了 2 个)、main.ts / DragHandler.ts 保留过时的「800×600」注释。这类「代码和文档互相说谎」的地方,正是知识库应该重点写的东西。

6.2图上实际有哪 8 条边

#源概念→目标概念关系含义(由散文表达)
1架构总览→事件总线架构分层里事件解耦是核心机制
2产品全景与玩法规则→战场地图玩法里的三张地图指向 MapDef 配置
3产品全景与玩法规则→持久化键进度存档指向 localStorage 键
4战场地图→平衡仿真地图机制修饰需要仿真验证难度曲线
5防御塔→强化修饰器塔属性计算链读全局 buff 乘区
6已知注意点→强化修饰器坑位清单里「描述与实际乘区不一致」在此
7合成音效→持久化键静音开关的持久化落点
8构建与运行→平衡仿真仿真脚本是构建脚本的一部分
render_viz.py 产出的交互式知识图谱
图 3render_viz.py 的产物。左侧是力导向图(节点大小 = 正文长度,灰色是默认色,绿色是 type: Reference),右侧是点击节点后的详情面板:type chip、id、status / trust tier badge、Description / Resource / Tags / Generated / Sources 字段区,以及 marked 渲染的正文——正文里能直接看到 [^game-src] 脚注与指向源码的资源链接。整页零外部请求,可以离线打开、也可以直接发给同事。

07常见坑速查

前六条来自 SKILL.md 的踩坑记录,后四条是本次源码研读 + 实测补充的。

#现象根因处理
1解析 index.md / log.md 时 IndexError它们没有 frontmatter,「按 split('---') 取第 2 段」拿不到第二段任何此类逻辑必须先跳过保留文件名
2链接改完 grep 看着没问题,图谱还是错编辑器报「保存成功」但落盘没生效(历史真实案例)以重新读文件为准;校验脚本跑绿才算完成
3resource 指向了不存在的位置路径基准搞错:resource 从文档自身位置起算okf/<分区>/x.md 引仓库文件写 ../../…,不是按 bundle 根算
4viz 里链接整体错位一级上游 viewer 以 bundle 根解析一切链接,且只 rewire / 开头的 .md内置 okf_viewer 已含规范化补丁,直接用即可;同步上游时按 generator-patch.md 重放
5校验器报「脚注无对应 sources id」,但正文里那段是示例代码块里的 [^x]: 被当成真脚注定义所有文本扫描都在 strip_code_blocks() 之后做
6知识库全是「废话」大仓库想全读 → 只能复述目录结构;或凭印象补参数按「每模块精读核心文件」收敛;编造的参数比缺失更糟
7概念数 21,图上却 22 个节点,types 里冒出 Unknown_walk_concepts 只跳过 index.md,log.md 被当概念,无 frontmatter → type 落 Unknown知情即可(见 6.4);要消掉就在过滤条件里一并跳过 log.md
8仓库根基准链接(/okf/…)全部失效,edges 归零_repo_root_abs() 的映射前缀是 /{bundle 目录名}/。实测:把 bundle 复制成 okf_stats_td/ 再渲染,22 个节点只剩 0 条边;目录名恢复为 okf 后立刻回到 8 条bundle 目录就叫 okf,且放在仓库根下(补丁 6 以 bundle_root.parent 为仓库根)。改名 / 搬家后必须重跑渲染确认 edges 数
9代码仓库的图谱全是灰点,看不出模块差异调色板只定义 3 种 BigQuery 场景的 type,其余全走默认灰用 type 下拉或搜索定位;若要按模块着色需自行扩展 _TYPE_PALETTE
10同一路径在 bundle 内和仓库里都存在,渲染却指向了意外的那个/ 开头链接存在双重解析规则:校验器「bundle 根 → 仓库根」任一存在即通过,渲染器以 bundle 根为准避免在 bundle 内放与仓库同名的路径,从命名上消除歧义
关于第 8 条:这不是「坑」,而是一条隐含前提

整套链接约定(正文 /okf/分区/x.md)只在「bundle 位于仓库根、且目录名恰为 okf」的布局下成立。若把 bundle 放到 docs/okf/ 或改名,仓库根基准的链接不会被映射,必须改用 bundle 根基准写法(/分区/x.md)——那种形式上游原生支持,不需要任何补丁。换句话说:先确定布局,再确定链接写法。

08边界与许可

8.1技能不做什么

  • 不实现 Attested Computation。规范 §10 定义了「可证明计算」(runtime / parameters / executor / receipt / attester),但那是数据仓库场景的运行时协议,本技能完全不涉及。若你的场景需要「确认 Agent 跑的是官方批准的计算」,这颗能力目前是空的。
  • 不做增量同步。它是一次性的生成工作流;代码变更后要重新跑,靠 generated.at 记录新鲜度,而不是自动 diff 更新。
  • 不替你确认内容正确性。产出全部停在 unverified,人工复核是独立动作。
  • 渲染器的图边只认 .md 链接。指向 URL 或非 markdown 资源的链接不进图、只进详情面板的 Sources 区。

8.2依赖与许可

组件来源许可
SKILL.md 工作流、两个脚本、README本仓库自研MIT
references/SPEC.md(OKF v0.2 规范快照,commit 0b87c52)GoogleCloudPlatform/open-knowledge-formatApache 2.0(副本见 SPEC-UPSTREAM-LICENSE.md)
references/usage-guide.zh.md(上游中文指南快照)同上Apache 2.0;其中讲上游 BigQuery 生产 agent 的 §3 / §4.1–4.2 / §5 A·B / §6 enrich / §8 与本工作流无关
scripts/okf_viewer/(渲染包,含链接规范化补丁)同上 viewerApache 2.0
static/vendor/cytoscape.min.js 3.28.1cytoscape/cytoscape.jsMIT
static/vendor/marked.min.js 12.0.0markedjs/markedMIT

全部上游快照都已内置,无需 clone 上游仓库,也无需联网。上游 viewer 更新时按各文件头部溯源注释与 references/generator-patch.md 重新同步;补丁本身是通用修复(对官方 bundle 零影响、修正规范矛盾),适合整理成 PR 提给上游——合入后即可去掉这处本地差异。

8.3一句话总结

这个技能的本质是一条被约束住的写作纪律:读源码 → 只写有依据的事实 → 每条论断挂上归因 → 用脚本证明没有断链和孤儿脚注 → 诚实标注「没人复核过」。格式与工具都只是为了让这条纪律可检查、可 diff、可离线分发。