299 lines
64 KiB
HTML
299 lines
64 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>知识库索引 — github-learn</title>
|
||
<style>
|
||
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
|
||
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans SC",sans-serif;background:#f8fafc;color:#1e293b;line-height:1.7}
|
||
.wrapper{max-width:900px;margin:0 auto;padding:0 20px}
|
||
header{background:linear-gradient(135deg,#0f172a 0%,#1e3a5f 100%);color:#f1f5f9;padding:48px 0 40px;margin-bottom:40px}
|
||
header h1{font-size:1.6rem;font-weight:700;margin-bottom:6px}
|
||
header .sub{font-size:.85rem;color:#94a3b8}
|
||
.search-bar{margin-bottom:12px}
|
||
.search-bar input{width:100%;padding:12px 16px;border:2px solid #e2e8f0;border-radius:8px;font-size:.95rem;outline:none;transition:border-color .2s;font-family:inherit}
|
||
.search-bar input:focus{border-color:#3b82f6}
|
||
.filter-row{display:flex;align-items:center;gap:10px;margin-bottom:24px;flex-wrap:wrap}
|
||
.filter-row label{font-size:.85rem;color:#64748b;font-weight:600}
|
||
.filter-row select{padding:8px 12px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;color:#1e293b;font-size:.88rem;font-family:inherit;outline:none}
|
||
.filter-row select:focus{border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.12)}
|
||
.clear-filters{padding:8px 12px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;color:#475569;font-size:.88rem;font-family:inherit;cursor:pointer;transition:all .15s}
|
||
.clear-filters:hover{background:#f1f5f9;border-color:#94a3b8;color:#1e293b}
|
||
.clear-filters:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.12)}
|
||
.no-results{text-align:center;padding:40px 20px;color:#94a3b8;display:none}
|
||
.no-results.visible{display:block}
|
||
.tag-cloud{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:32px}
|
||
.tag-badge{background:#eff6ff;color:#1d4ed8;border:1px solid #bfdbfe;padding:4px 12px;border-radius:16px;font-size:.8rem;cursor:pointer;user-select:none;transition:all .15s}
|
||
.tag-badge:hover{background:#dbeafe;border-color:#93c5fd}
|
||
.tag-badge.active{background:#1d4ed8;color:#fff;border-color:#1d4ed8}
|
||
.tag-badge .count{font-size:.7rem;opacity:.7;margin-left:2px}
|
||
.entries{margin-bottom:48px}
|
||
.entry-card{background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:22px 24px;margin-bottom:16px;transition:box-shadow .15s}
|
||
.entry-card:hover{box-shadow:0 2px 12px rgba(0,0,0,.06)}
|
||
.entry-card.hidden{display:none}
|
||
.entry-header{display:flex;justify-content:space-between;align-items:baseline;flex-wrap:wrap;gap:8px;margin-bottom:8px}
|
||
.entry-title{font-size:1.15rem;font-weight:700;color:#0f172a}
|
||
.entry-date{font-size:.8rem;color:#94a3b8}
|
||
.entry-meta{font-size:.8rem;color:#64748b;margin-bottom:10px}
|
||
.entry-tags{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:10px}
|
||
.entry-tags .mini-tag{background:#f1f5f9;color:#475569;padding:2px 8px;border-radius:10px;font-size:.73rem;cursor:pointer;transition:all .12s}
|
||
.entry-tags .mini-tag:hover{background:#e2e8f0}
|
||
.entry-tags .mini-tag.match{background:#fef3c7;color:#92400e}
|
||
.entry-body{font-size:.88rem;color:#475569;line-height:1.65;max-height:100px;overflow:hidden;position:relative}
|
||
.entry-body::after{content:'';position:absolute;bottom:0;left:0;right:0;height:30px;background:linear-gradient(transparent,#fff)}
|
||
.related-section{margin-top:12px;padding-top:10px;border-top:1px dashed #e2e8f0;font-size:.8rem}
|
||
.related-section .related-label{color:#94a3b8;margin-bottom:4px}
|
||
.related-section a{color:#3b82f6;text-decoration:none;margin-right:8px;cursor:pointer}
|
||
.related-section a:hover{text-decoration:underline}
|
||
mark{background:#fde68a;color:#1e293b;padding:0 2px;border-radius:2px}
|
||
footer{text-align:center;padding:24px 0;border-top:1px solid #e2e8f0;color:#94a3b8;font-size:.8rem;margin-top:20px}
|
||
@media(max-width:640px){header h1{font-size:1.3rem}.entry-card{padding:16px}}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<header>
|
||
<div class="wrapper">
|
||
<h1>知识库索引</h1>
|
||
<div class="sub">github-learn · 共 <span id="entry-count">0</span> 条知识条目</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="wrapper" id="content-area">
|
||
|
||
<div class="search-bar">
|
||
<input type="text" id="search-input" placeholder="搜索标题、标签或正文..." autocomplete="off">
|
||
</div>
|
||
|
||
<div class="filter-row">
|
||
<label for="year-filter">年份</label>
|
||
<select id="year-filter"><option value="">全部年份</option></select>
|
||
<button type="button" class="clear-filters" id="clear-filters">清空筛选</button>
|
||
</div>
|
||
|
||
<div class="no-results" id="no-results">没有找到匹配的条目</div>
|
||
|
||
<div class="tag-cloud" id="tag-cloud"></div>
|
||
|
||
<div class="entries" id="entries"></div>
|
||
|
||
<footer>
|
||
由 scripts/update-knowledge-index.sh 生成 · <span id="gen-time"></span>
|
||
</footer>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
const ENTRIES = [
|
||
{ slug: 'Waza', path: 'knowledge/entries/knowledge_20260417_Waza', date: '20260417', title: 'Waza — 把工程师的习惯变成 Claude 可执行的技能', author: '叫我小杨同学的小码酱', tags: ['Claude Code', 'Skills', 'AI 辅助开发', '工程习惯', 'tw93'], body: ' # Waza:你知道的工程习惯,变成 Claude 能跑的技能 > **一句话核心**:Waza(技)把优秀工程师的思维方式打包成 8 个 Claude Code 技能 —— 不是替你写代码更快,而是逼你想清楚再动手。 > > **认知挂钩**:像道场里的型(Kata)。每个技能是一个固定套路,练到变成肌肉记忆。 > > **真理锚点**:*"AI makes you faster. It doesn\'t make you think more clearly."* ## 模块 0:核心摘要 (TL;DR) Waza 是开发者 **tw93** 开源的 Claude Code 技能集(3.3k+ Stars),将 8 个核心工程习惯封装为 `/` 斜杠命令。它不追求"全能",而是聚焦**真正重要的习惯**:先思考再动手、写完自己审、bug 系统排查、界面有审美、文章写得顺、新领域靠输出学、文档当一手资料读、开发环境定期体检。 **生活类比**:不是给你一把更快的锤子,而是教你先看图纸、再选工具、最后才敲。 ## 模块 1:概念破冰 ### 巧记卡片 <div class="mnemonic-card"> **八字口诀**:**思设审猎,写学读健** | 字 | 技能 | 阶段 | |---|---|---| | **思** | `/think` | 动手前:挑战问题、压力测试设计 | | **设** | `/design` | 做界面:产出有辨识度的 UI | | **审** | `/check` | 合并前:自审 diff、标记危险操作 | | **猎** | `/hunt` | 出 bug 时:系统调试、确认根因再修 | | **写** | `/write` | 写文档:中英双语自然表达 | | **学** | `/learn` | 新领域:六阶段研究 → 输出 → 自审 → 发布 | | **读** | `/read` | 读资料:URL/PDF 转干净 Markdown | | **健** | `/health` | 定期体检:CLAUDE.md、rules、skills、hooks、MCP | </div> ### 故事引入 想象两个工程师。 A 接到需求直接写代码,写完直接提交。遇到 bug 就猜,试十个地方碰巧修好。文档写得像机翻。 B 接到需求先问:这个问题真的存在吗?有没有更简单的解法?写完代码自己过一遍 diff。遇到 bug 不猜,先复现、定位、确认根因再修。文档写得连外行都能懂。 AI 让 A 写得更快了,但还是 A。AI 让 B 变成了超级 B。 Waza 就是给 B 准备的那套工具。 ### 架构概览 ``` ┌─────────────────────────────────────────────────┐ │ Waza 技能矩阵 │ ├─────────────────────────────────────────────────┤ │ │ │ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ │ │ │/think │→ │/design│→ │/check │ │/hunt │ │ │ │ 思考 │ │ 设计 │ │ 审查 │ │ 调试 │ │ │ └───────┘ └───────┘ └───────┘ └───────┘ │ │ ↑ ↑ │ │ │ ┌───────┐ │ │ │ └────────│/write │───────────┘ │ │ │ 写作 │ │ │ └───────┘ │ │ │ │ ┌───────┐ ┌───────┐ ┌───────┐ │ │ │/learn │ │ /read │ │/health│ │ │ │ 学习 │ │ 阅读 │ │ 体检 │ │ │ └───────┘ └───────┘ └───────┘ │ │ 输入 ──────→ 转化 ──────→ 输出 │ │ │ └─────────────────────────────────────────────────┘ ``` ## 模块 2:深度解析 ### 哲学:为什么是"习惯"而不是"规则"? Waza 的名字来自日语"技"(わざ),武道中意为"练到成本能的招式"。这与市面上大多数 AI 技能包有根本区别: **规则驱动 vs 习惯驱动** | 维度 | 规则驱动(Superpowers/gstack 类) | 习惯驱动(Waza) | |---|---|---| | 指令风格 | 大量 detailed rules,步步规定 | 设目标 + 约束,然后放手 | | 模型上限 | 指令写多少,模型做多少——指令成了天花板 | 约束关键边界,其余让模型自由发挥 | | 模型进化 | 模型变强后,旧规则可能变成束缚 | 模型变强,自由度带来的收益呈复利增长 | | 学习曲线 | 陡峭,配置多 | 扁平,每个技能一个触发场景 | **核心洞察**:作者写下的每一条规则都成了模型能力的天花板。Waza 反其道而行——每个技能设明确目标,退后一步让模型发挥。 ### 8 个技能的工程生命周期 ```mermaid flowchart TD A["开始新任务"] --> B["/read: 读取相关文档、RFC、PR"] B --> C["/think: 挑战问题本身,验证架构"] C --> D{"前端界面?"} D -->|"是"| E["/design: 产出有审美的 UI"] D -->|"否"| F["编码实现"] E --> F F --> G{"遇到 bug?"} G -->|"是"| H["/hunt: 系统调试,确认根因"] G -->|"否"| I["/check: 自审 diff"] H --> I I --> J{"写作/文档?"} J -->|"是"| K["/write: 润色中英双语"] J -->|"否"| L["完成"] K --> L M["定期"] --> N["/health: 体检 Claude 环境"] O["遇到新领域"] --> P["/learn: 六阶段研究"] ``` ### 逐技能拆解 #### 1. `/think` — 先想清楚,再动手 **触发**:开始任何新任务之前。 **做什么**:挑战问题本身。需求是真的吗?有没有更简单的解法?架构有没有隐患? **核心价值**:防止"用正确的方式做错误的事"——这是工程师最常见的浪费。 #### 2. `/design` — 界面要有辨识度 **触发**:构建前端界面时。 **做什么**:产出有明确审美方向的 UI,不是千篇一律的默认样式。 **核心价值**:AI 默认生成"能用但丑"的界面。这个技能逼 Claude 做出有设计感的东西。 #### 3. `/check` — 合并前的最后一道关 **触发**:完成任务后、合并代码前。 **做什么**:审查 diff,自动修复安全的问题,标记危险命令,用证据说话。 **核心价值**:像老工程师坐在你旁边 review——但比你主动。支持并行多专家审查(宿主环境支持时)。 #### 4. `/hunt` — 系统调试,不靠猜 **触发**:任何 bug 或异常行为。 **做什么**:先复现,再定位,确认根因后才修。 **核心价值**:工程师最容易犯的错——看到 bug 就猜。猜 10 次碰巧修了 1 次,剩下 9 次埋了新雷。 #### 5. `/write` — 像人一样写文章 **触发**:撰写或编辑文档。 **做什么**:重写中英双语,去掉生硬公式化表达。 **核心价值**:AI 生成的文档读起来像翻译腔。这个技能让文字有"人味"。 #### 6. `/learn` — 六阶段研究法 **触发**:深入不熟悉的领域。 **流程**:收集 → 消化 → 大纲 → 填充 → 精炼 → 自审 → 发布。 **核心价值**:学习新领域靠产出驱动,而不是消费内容。先写再改再发。 #### 7. `/read` — 把一切变成干净 Markdown **触发**:任何 URL 或 PDF。 **做什么**:抓取内容转为干净 Markdown,特殊处理 GitHub、PDF、微信、飞书。 **核心价值**:省去手动复制粘贴和格式清理的时间。 #### 8. `/health` — Claude 环境的体检报告 **触发**:审计 Claude Code 设置时。 **检查项**:CLAUDE.md、rules、skills、hooks、MCP、行为表现。 **核心价值**:按严重程度分级标记问题,防止配置腐烂。基于作者的[六层框架](https://tw93.fun/en/2026-03-12/claude.html)。 ### 项目起源与数据 Waza 不是凭空设计的。它来自真实项目的失败积累: - 找错代码路径,来回 4 轮才定位 - 发布 release 前忘了上传 artifacts - 服务器重启 8 次都没看报错信息 **30 天、300+ 次会话、7 个项目、500 小时** —— 每个 "gotcha" 都对应一次真实失败。 ## 模块 3:深度裂变 <div class="fission-section"> ### 矛盾分析 & 常识颠覆 #### 1. "不完整是设计出来的" > Waza 只有 8 个技能。不是做不到更多,而是**刻意不做完**。 市面上的 AI 技能包动辄几十个技能,每个覆盖一个小场景。Waza 反其道:**八个习惯,每个做一件事,有明确触发条件,然后让路**。 **核爆级结论**:对 AI 工具来说,"够用"比"全能"更有价值。因为每个技能都是独立可调用的,组合起来覆盖工作流全链路,但每个单独调用时负担极小。 #### 2. "每条规则都是天花板" > 作者写的每一条规则,都成了模型能力的上限。 这是 Waza 最反直觉的设计哲学。传统做法是"把所有规则写进 prompt",但这隐含一个假设:作者比模型聪明。Waza 的做法是"设目标 + 约束,然后放手"——等模型变强了,自由度带来的收益会呈复利。 **搜索内化**:在 2026 年的 AI 辅助开发社区中,"less prompt engineering, more outcome-driven constraints" 正成为新共识。Waza 是这一理念的极端实践者。 #### 3. "英文推理更强"的隐性红利 > 项目专门提供了 English Coaching 规则,建议用英文与 AI 交互。 理由很朴素:大多数 AI 模型的英文训练量远超其他语言。母语写 prompt → 隐形翻译层 → 推理质量打折。切换英文后,回答更精准,顺便练英语。 **争议点**:这对非英语母语用户有门槛。Waza 的做法是**不强求**,但提供工具(`english.md` 规则)让 Claude 在英文交互时即时纠错。 </div> ## 模块 4:实战指南 ### 如何开始 ```bash # 一步安装所有技能(Claude Code) npx skills add tw93/Waza -a claude-code -g -y # 一步安装所有技能(Codex) npx skills add tw93/Waza -a codex -g -y # 可选:安装 statusline 显示上下文用量 curl -sL https://raw.githubusercontent.com/tw93/Waza/main/scripts/setup-statusline.sh | bash # 可选:安装英文教练规则 mkdir -p ~/.claude/rules && curl -fsSL https://raw.githubusercontent.com/tw93/Waza/main/rules/english.md -o ~/.claude/rules/english.md ``` ### 推荐工作流 ``` 需求来了 → /think 先挑战问题 → /read 读取相关文档 → 编码(前端先 /design) → 遇到 bug → /hunt → 写完 → /check 自审 → 写文档 → /write 润色 → 新领域 → /learn 研究 → 定期 → /health 体检 ``` ### 避坑指南 | 反模式 | 后果 | 正确做法 | |---|---|---| | 跳过 `/think` 直接写 | 做了错误的事,返工成本高 | 再急也先想 5 分钟 | | `/hunt` 时直接猜修复 | 埋新雷 | 先复现,确认根因 | | 不看 `/check` 结果就合并 | 危险命令进主干 | 审查完再合 | | 装了技能从不调用 | 形同虚设 | 养成肌肉记忆,每次任务触发对应技能 | | 忽略 `/health` | 配置逐渐腐烂 | 每周跑一次 | ### ROI 分析 | 投入 | 回报 | |---|---| | 安装 5 分钟 | 每个任务避免至少 1 次返工 | | `/think` 多花 5 分钟 | 可能省下 2 小时重写 | | `/check` 多花 2 分钟 | 避免线上事故 | | `/learn` 多花 30 分钟 | 产出 > 消费 10 倍效率 | ## 模块 5:温故知新 ### FAQ <details> <summary><b>Q1: Waza 和其他 Claude Code 技能包(如 Superpowers、gstack)有什么区别?</b></summary> <p>Superpowers 和 gstack 功能更全但更重——技能多、配置多、学习曲线陡。Waza 只做 8 个最核心的习惯,每个一件事,触发条件清晰。哲学不同:规则驱动 vs 习惯驱动。</p> </details> <details> <summary><b>Q2: 只能在 Claude Code 里用吗?</b></summary> <p>不。<code>/health</code> 是 Claude Code 独有的(需要检查环境)。其余 7 个技能使用宿主环境的原生 question/search/fetch/agent 机制,也支持 Codex。</p> </details> <details> <summary><b>Q3: 这些技能是固定死的吗?可以自己改吗?</b></summary> <p>每个技能是一个文件夹(不只是 Markdown 文件),包含参考文档、辅助脚本、gotchas。你可以 fork 后按需修改。MIT 协议。</p> </details> <details> <summary><b>Q4: Waza 适合什么水平的开发者?</b></summary> <p>有工程经验但想更系统化的开发者。如果你已经有这些习惯,Waza 帮你自动化。如果你还没有,Waza 逼你养成。</p> </details> <details> <summary><b>Q5: "Waza" 这个名字怎么念?</b></summary> <p>日语「技」(わざ / waza),发音类似 "哇扎"。在武道中指"练到成本能的招式"。</p> </details> <details> <summary><b>Q6: 作者 tw93 是谁?</b></summary> <p>活跃在 GitHub 和 Twitter 的独立开发者,也是 MiaoYan 等项目的作者。养了两只猫:汤圆和可乐。</p> </details> <details> <summary><b>Q7: 最新版本是什么?</b></summary> <p>截至 2026-04-17,最新版本为 V3.10.0,包含 252 次 commits,3.3k+ stars,202 forks。</p> </details> <details> <summary><b>Q8: 怎么卸载?</b></summary> <pre><code># 移除所有技能 npx skills remove tw93/Waza -g # 移除 statusline rm -f ~/.claude/statusline.sh # 然后从 ~/.claude/settings.json 中删除 statusLine 键 # 移除英文教练 rm -f ~/.claude/rules/english.md</code></pre> </details> ### 自测题 1. **理解层**:Waza 的核心哲学是什么?为什么"不完整是设计出来的"? 2. **记忆层**:8 个技能分别是什么?各自在什么场景触发? 3. **分析层**:如果跳过 `/think` 直接编码,最大的风险是什么?请举一个你经历过的例子。 4. **应用层**:你接手一个全新项目,描述从接到需求到合并代码的完整 Waza 工作流。 5. **批判层**:Waza 只有 8 个技能。你觉得缺了什么?为什么作者可能故意不做? 6. **迁移层**:你如何在现有工作流中引入 Waza 技能?哪些最容易养成习惯?哪些最难? 7. **创造层**:如果你要给 Waza 贡献第 9 个技能,会是什么?写一个简短的 SKILL.md 大纲。 ### 参考资源 - [tw93/Waza GitHub 仓库](https://github.com/tw93/Waza) - [作者博客:Claude Code 六层框架](https://tw93.fun/en/2026-03-12/claude.html) - [Waza 演示推文](https://x.com/HiTw93/status/2041312649510822103) ' },
|
||
{ slug: 'mattpocock_skills', path: 'knowledge/entries/knowledge_20260518_mattpocock_skills', date: '20260518', title: 'mattpocock/skills 深度解析:AI Agent 工作流的工程化革命', author: '叫我小杨同学的小码酱', tags: ['Claude Code', 'Agent Skills', 'AI Engineering', 'Workflow', 'Matt Pocock', 'SKILL.md'], body: ' # mattpocock/skills 深度解析:AI Agent 工作流的工程化革命 ## 模块 0:核心摘要 (TL;DR) > **一句话核心**:Matt Pocock 将自己在 Claude Code 中打磨了数月的 AI 协作工作流,打包成可复用、可组合的 SKILL.md 技能包,开启了"AI 技能包管理"的工程化时代。 **认知挂钩**:就像 jQuery 插件让前端开发从"每次都从头写 JS"进化到"装个插件就行",mattpocock/skills 让 AI 编程从"每次都从头调教 AI"进化到"装个 Skill 就行"——它定义了 AI Agent 指令的封装标准。 **真理锚点**:*"Skills for Real Engineers. Straight from my .claude directory."* —— Matt Pocock ## 模块 1:概念破冰 (Concept Ice-breaking) ### 巧记卡片 ``` AI 编程三板斧: 一装技能包,行为有 template(模板化) 二写 SKILL.md,流程有 blueprint(蓝图化) 三用 npx skills,分发有 package(工程化) ``` ### 故事引入 想象一下:你新招了一个能力超强的实习生 Claude。每次让他写代码,你都得花 20 分钟交代一遍:"先写测试、再实现、再重构。不要直接改代码,先问我。Git push 之前必须确认。" 一个月后你崩溃了——**每次对话都要重新教一遍**。 Matt Pocock 也遇到过这个问题。他的解决方案不是"记住我说的话",而是**把这些指令打包成一个个可复用的"技能包"**,像乐高积木一样按需装载。于是在2026年2月3日,他把自己的 `.claude/skills/` 目录开源了——mattpocock/skills 诞生。 **结果**:不到 3 个月,这个仓库飙到 58k+ Stars,成为 AI 编程领域的现象级项目。 ### 可视化 ``` 传统 AI 编程: Skill 化之后: ┌──────────────────┐ ┌──────────────────┐ │ "Claude,先写测试"│ │ /tdd 一键加载 │ │ "Claude,别推代码"│ → │ /grill-me 审需求 │ │ "Claude,问清楚" │ │ /diagnose 修bug │ │ 每次都重说一遍 │ │ 标准化即插即用 │ └──────────────────┘ └──────────────────┘ ``` ## 模块 2:深度解析 (Deep Analysis) ### 2.1 三个核心设计问题 Matt Pocock 的 skills 仓库之所以能引爆社区,是因为它精准地回答了三个问题: **Q1: 如何让 AI 记住大量指令而不撑爆上下文?** → **三层渐进加载 (Progressive 3-Layer Loading)** **Q2: 如何让技能包可被发现、可组合?** → **SKILL.md 标准化 + npx skills 包管理器** **Q3: 如何让技能真正可复用而不是一次性提示词?** → **依赖注入模式:setup-matt-pocock-skills** ### 2.2 架构核心:三层渐进加载 (3-Layer Loading) 这是整个系统的基石。Claude Code 的上下文窗口就像一间小公寓——你不能把所有东西都堆进去。 ```mermaid flowchart TD A["Session Init"] --> B["Layer 1"] subgraph B["Layer 1: Discovery"] B1["扫描 .claude/skills/*/SKILL.md"] B2["仅加载 name + description(~100 tokens)"] end B --> C{"用户触发匹配?"} C -- "否" --> D["停留在 L1,0 额外开销"] C -- "是(如输入 /tdd)" --> E["Layer 2"] subgraph E["Layer 2: Activation"] E1["加载完整 SKILL.md 正文"] E2["注入系统提示词"] E3["~5000 tokens"] end E --> F{"指令中引用外部资源?"} F -- "否" --> G["技能执行"] F -- "是(如 references/ 目录)" --> H["Layer 3"] subgraph H["Layer 3: Penetration"] H1["按需读取 references/*.md"] H2["按需执行 scripts/*.py"] H3["可变 tokens"] end H --> G G --> I["输出结果"] ``` **设计妙处**:这个机制借鉴了操作系统虚拟内存的"按需分页"思想——只加载当前需要的部分,极大节省了上下文空间。如果你有 20 个技能,每个占 5000 tokens,一次性加载就是 100k tokens。但有了分层设计,实际消耗仅 2k tokens 左右(20 × 100 = 2000)。 ### 2.3 SKILL.md 格式规范 每个技能的核心是一个 Markdown 文件,带 YAML 前置元数据: ```markdown name: tdd description: "Red-Green-Refactor TDD 循环" version: "1.0.0" user-invocable: true allowed-tools: [Read, Write, Bash, Grep] tags: [testing, tdd, development] # TDD 技能 ## Role Definition 你是 TDD 驱动开发专家... ## Workflow 1. **Red** — 先写一个会失败的测试 2. **Green** — 写最少代码让测试通过 3. **Refactor** — 优化代码,保持绿色 ## Constraints - 严禁跳过 Red 阶段 - 每次重构后运行全部测试 ``` **YAML 字段详解**: | 字段 | 约束 | 用途 | |------|------|------| | `name` | kebab-case,≤64字符 | 唯一标识(也是 slash command 名) | | `description` | ≤1024字符 | L1 加载项,技能发现用 | | `version` | semver | 版本管理 | | `user-invocable` | boolean | 是否可通过 `/name` 调用 | | `allowed-tools` | 数组 | 技能运行时授予的工具权限 | | `tags` | 数组 | 用于搜索分类 | ### 2.4 目录结构 ``` .claude/skills/<skill-name>/ ├── SKILL.md # 必需 —— 技能的核心 ├── REFERENCE.md # 可选 —— API 文档、规则 ├── EXAMPLES.md # 可选 —— few-shot 示例 ├── TROUBLESHOOTING.md # 可选 —— 常见问题 ├── scripts/ # 可选 —— 可执行脚本 │ ├── process.py │ └── utils.js ├── references/ # 可选 —— 长文档 │ └── style-guide.md ├── templates/ # 可选 —— 输出模板 │ └── report-template.txt └── resources/ # 可选 —— 数据文件 └── template.xlsx ``` **渐进披露的精髓**:`SKILL.md` 保持足够短(<5000 tokens),只写核心流程。所有长文档放在 `references/`,仅在需要时由 `SKILL.md` 中的指令触发加载。这样既保证了功能的完整性,又维持了上下文的轻量。 ### 2.5 22 个技能全景 Matt Pocock 的仓库包含约 22 个 SKILL.md 文件,覆盖 4 个大类: #### 工程类 (Engineering) | 技能 | 功能 | 设计亮点 | |------|------|---------| | **grill-me** | 编码前的需求追问 | 18+ 问题穷举盲点,不写代码只提问 | | **grill-with-docs** | 需求追问+文档生成 | 在 grill 基础上产出文档产物 | | **tdd** | 红绿重构 TDD 循环 | 强制不可跳过 Red 阶段 | | **diagnose** | Bug 科学排查循环 | 基于假说-验证的 debug 方法论 | | **triage** | GitHub Issue 分类 | 状态机驱动的标签化管理 | | **to-prd** | 对话→PRD 生成 | 将模糊需求转化为结构化的 PRD | | **to-issues** | PRD→GitHub Issues | 垂直切片拆解,而非分层拆解 | | **improve-codebase-architecture** | 架构改进建议 | 识别技术债并提出渐进式改进 | | **zoom-out** | 代码库高空视角 | 整体架构概览,不漏细节 | | **prototype** | 快速原型 | 明确标记为"可丢弃" | #### 效率类 (Productivity) | 技能 | 功能 | 设计亮点 | |------|------|---------| | **caveman** | 压缩沟通模式 | 减少约 75% token 消耗的极简回复 | | **handoff** | Agent 间交接文档 | 结构化的上下文移交格式 | | **write-a-skill** | 元技能——写新技能 | 自举设计,系统可自我扩展 | #### 工具类 (Tooling & Setup) | 技能 | 功能 | |------|------| | **setup-matt-pocock-skills** | 一键初始化全局配置 | | **git-guardrails-claude-code** | 拦截危险 git 命令 | | **setup-pre-commit** | Husky + lint-staged 配置 | | **scaffold-exercises** | 练习目录脚手架生成 | | **migrate-to-shoehorn** | 测试断言迁移工具 | ### 2.6 核心设计模式 #### 模式 A: 依赖注入 (Dependency Injection) `setup-matt-pocock-skills` 在首次运行时,自动检测项目环境: - git remote → 检测 issue tracker - 已有标签 → 合并,而非替换 - 项目类型 → 选择合适的模板 结果写入 `docs/agents/` 目录下的项目配置文件。 **类比**:就像 Spring 的 IoC 容器——技能是"通用逻辑",项目配置是"注入的依赖"。 #### 模式 B: Grill Me 的对抗式需求澄清 这是一个反直觉的设计——**让 AI 扮演一个"烦人的同事"**,不断对你的设计方案提出质疑。它不写一行代码,只提问: > "你考虑过边界情况吗?这个接口的调用方是谁?错误处理策略是什么?如果用户输入为空怎么办?这个方案的性能瓶颈在哪里?..." **为什么有效**:人类在表达时容易陷入"知识的诅咒"——以为别人知道的和自己一样多。Grill Me 通过强制外化思维过程,暴露了那些"你以为想清楚了但其实没有"的盲区。 #### 模式 C: 垂直切片 (Vertical Slicing) `to-issues` 将 PRD 拆解为用户故事的粒度,而非技术层粒度。 **错误方式**(水平分层): - Issue 1: 写数据库模型 - Issue 2: 写 API 接口 - Issue 3: 写前端页面 **正确方式**(垂直切片): - Issue 1: 用户可以注册(数据库 + API + 前端) - Issue 2: 用户可以登录(数据库 + API + 前端) - Issue 3: 用户可以查看个人资料 **原因**:每个垂直切片都是**可独立交付**的——开发完一个就真正能用,而不是"所有模型都写完了但啥也看不到"。 #### 模式 D: Git Guardrails 这个技能本质上是一个**安全代理**,它拦截以下操作: - `git push` → 要求先拉取最新代码 - `git reset --hard` → 要求显示将被丢弃的变更 - `git clean -fd` → 需要明确确认 **哲学**:AI 执行速度很快,但快意味着"犯错更快"。Guardrails 是"慢下来,确保正确"的机制。 ## 模块 3:深度裂变 (Deep Fission) ### 🔍 颠覆认知:这不是"Prompt 合集",而是"软件工程范式转移" 大多数人对这个仓库的第一反应是:"哦,一堆 Claude 提示词模板。" **大错特错。** 只要仔细分析,你会发现这个仓库实际上在做三件比"提示词"深刻得多的事情: #### 裂变点 1: 从 REPL 到 File System 传统的 AI 交互是 **REPL(Read-Eval-Print Loop)** 模式——你问一句,AI 答一句,所有状态在对话中流转。而 SKILL.md 的本质是将认知状态**持久化到文件系统**: ``` REPL 模式: 人类大脑 ←→ AI 上下文 Skill 模式: 人类大脑 ←→ [文件系统] ←→ AI 上下文 ↑__ 可检查、可版本控制、可复用 __↑ ``` 当 `to-prd` 将对话内容生成为 PRD 文件时,它不再是对话中的一段文字——它是一个可审查、可修改、可版本控制的**制品**。这是 AI 交互从"瞬时对话"到"工程工件"的质变。 #### 裂变点 2: 元技能——系统的自举进化 `write-a-skill` 是整座大厦的基石。它是一个**写技能的技能**。这意味着: > 这套系统不需要外部维护者——AI 自己就能扩展自己的能力边界。 如果你遇到一个需要新技能的场景,你不需要等 Matt Pocock 发 PR。你只需要运行 `/write-a-skill`,AI 就会引导你创建新的 SKILL.md,然后它立刻就能用。这实际上是 Agent 领域的**自举(Bootstrapping)**——与编译器中"用 C 写 C 编译器"异曲同工。 #### 裂变点 3: The Skill Economy 已现雏形 2026 年 4-5 月,mattpocock/skills 引爆后,社区迅速跟进了多个衍生项目: | 项目 | 定位 | |------|------| | **vercel-labs/skills** | `npx skills` CLI 工具,成为 Skill 的"npm" | | **ComposioHQ/awesome-codex-skills** | Codex 生态的技能集合 | | **vinvcn/mattpocock-skills-zh-CN** | 简体中文本地化版 | | **vskill** | 安全扫描增强版包管理器 | 最耐人寻味的是,有人已经开始在 **npm 上发布 SKILL.md 包**,将"认知指令"作为一种可分发的产品。这是一个全新的软件品类——**认知包 (Cognitive Packages)**。 🔍 **搜索内化**:根据多个来源验证,vercel-labs/skills 的 `find-skills` 技能安装量已超过 150 万次,头部技能的安装量达到了数十万级别。这已经不仅仅是"开发者玩具"的规模。 ## 模块 4:实战指南 (Actionable Guide) ### 4.1 如何开始 #### 快速安装(1 分钟) ```bash # 安装全部技能 npx skills@latest add mattpocock/skills # 安装单个技能(推荐新手这样) npx skills@latest add mattpocock/skills --skill grill-me npx skills@latest add mattpocock/skills --skill tdd npx skills@latest add mattpocock/skills --skill git-guardrails-claude-code ``` #### 初始化配置 ```bash # 在 Claude Code 中运行 /setup-matt-pocock-skills ``` 该命令会自动: 1. 检测你的 git remote 2. 设置 issue tracker 配置 3. 初始化 `docs/agents/` 目录 ### 4.2 推荐起步三件套 社区公认的"最小可用组合": ``` 1. git-guardrails-claude-code → 安全锁(零成本,100% 必要) 2. grill-me → 需求追问(防止冲代码) 3. tdd → TDD 循环(保证质量) ``` ### 4.3 如何自己写 Skill 参考 `/write-a-skill` 的引导流程: ```markdown name: my-custom-review description: "自定义代码审查技能" version: "1.0.0" user-invocable: true allowed-tools: [Read, Grep, Bash] # 我的代码审查技能 ## Role 你是一个专门审查 [XX 类型] 代码的专家。 ## Checklist 1. 检查 [关注点 A] 2. 检查 [关注点 B] 3. 检查 [关注点 C] ## Output Format 以 Markdown 表格输出审查结果。 ``` ### 4.4 避坑指南 | 🔴 反模式 | ✅ 正确做法 | |-----------|-----------| | 一个 SKILL.md 里塞满所有逻辑 | 保持 SKILL.md 精简,细节放 references/ | | 技能之间重复定义相同规则 | 通过配置分离(`docs/agents/`)共享 | | 忘记设置 `allowed-tools` | 明确声明技能需要哪些工具权限 | | 描述太长(超 1024 字符) | 描述越短,L1 发现越精准 | | 一次性写 10 个技能全装上 | 从 3 个核心技能开始,按需增加 | ### 4.5 ROI 分析 | 投入 | 产出 | |------|------| | 安装:1 分钟 | 每个会话节省 5-10 分钟"调教"时间 | | 学习:30 分钟熟悉各技能 | Bug 排查效率提升 2-3 倍 | | 自定义:1-2 小时写一个技能 | 团队标准统一,新人上手更快 | ## 模块 5:温故知新 (Consolidation) ### 常见陷阱 (FAQ) <details> <summary><strong>Q: 安装后技能不生效怎么办?</strong></summary> 检查是否在正确的目录下运行了 Claude Code。技能分为全局(`~/.claude/skills/`)和项目级(`./.claude/skills/`),确保安装位置正确。运行 `npx skills list` 查看已安装的技能。 </details> <details> <summary><strong>Q: SKILL.md 与其他 Markdown 文件的区别?</strong></summary> SKILL.md 需要 YAML 前置元数据(frontmatter),且必须有 `name` 和 `description` 字段。普通 .md 文件不会被 Claude Code 识别为技能。 </details> <details> <summary><strong>Q: 不同技能的指令冲突了怎么办?</strong></summary> Claude Code 会按技能激活顺序合并指令。如果冲突,后激活的技能不会覆盖先激活的。建议在各自 SKILL.md 中使用明确的范围限定词(比如"/diagnose 场景下")来避免冲突。 </details> <details> <summary><strong>Q: 可以在 Cursor / Copilot 中使用吗?</strong></summary> `npx skills` CLI 支持 55+ 个 Agent 平台,包括 Cursor、GitHub Copilot、Windsurf 等。但不同平台对 SKILL.md 的解析程度不同,建议在目标平台上测试。 </details> <details> <summary><strong>Q: 一个技能可以有多个文件吗?</strong></summary> 可以。SKILL.md 是入口点,可以通过 `scripts/` 目录引入脚本,通过 `references/` 引用长文档。但 L2 激活只会加载 SKILL.md 本体。 </details> <details> <summary><strong>Q: 如何更新已安装的技能?</strong></summary> 运行 `npx skills@latest update`。注意:目前有一个已知 bug(vercel-labs/skills#371),某些环境下 `npx skills update` 会静默失败,建议使用 `npx skills@latest add <repo> --skill <name> -g -y` 重新安装。 </details> <details> <summary><strong>Q: 技能会消耗大量 token 吗?</strong></summary> 不会。L1 阶段每个技能仅消耗约 100 tokens。L2 激活后才消耗约 5000 tokens。只有 L3 会按需扩展。对比一个复杂的任务可能消耗 20k+ tokens,技能的开销可以忽略不计。 </details> <details> <summary><strong>Q: 这个仓库和其他 Skill 集合相比好在哪里?</strong></summary> mattpocock/skills 的核心不是"数量多",而是"设计精良"。每个技能都遵循三层架构、渐进披露、垂直切片等设计原则,而不是简单地堆砌提示词。Matt 本人是 TypeScript 社区的核心人物,他的技能经过实际工程场景的打磨。 </details> ### 自测题 1. **SKILL.md 的三层加载机制是哪三层?各层分别加载什么?** 2. **YAML 前置元数据中,哪个字段控制技能是否可通过 `/name` 调用?** 3. **垂直切片(Vertical Slicing)与水平分层拆解 Issue 的区别是什么?为什么垂直切片更好?** 4. **`setup-matt-pocock-skills` 体现了什么设计模式?它解决了什么核心问题?** 5. **为什么 `write-a-skill` 是一个"元技能"?它有什么深远意义?** 6. **Git Guardrails 技能解决了什么核心问题?它拦截哪些操作?** 7. **Grill Me 技能的本质是什么?它为什么不写代码只提问?** 8. **如果要在团队中推广 SKILL.md 体系,你会先推荐哪 3 个核心技能?为什么?** ### 参考资源 - GitHub 仓库:https://github.com/mattpocock/skills - Vercel Labs Skills CLI:https://github.com/vercel-labs/skills - 中文翻译版:https://github.com/vinvcn/mattpocock-skills-zh-CN - 搜索安装:在 Claude Code 中运行 `/find-skills` *© 2026 叫我小杨同学的小码酱 | 知识吸收器 v3.0 | 真理锚定已通过* ' },
|
||
{ slug: 'CodeStable', path: 'knowledge/entries/knowledge_20260519_CodeStable', date: '20260519', title: 'CodeStable 深度解析:编排软件生命周期,而非编排 Agent', author: '叫我小杨同学的小码酱', tags: ['CodeStable', 'AI Engineering', 'Agent Skills', 'Harness Engineering', 'Human-in-the-Loop', 'OpenSpec', 'SuperPowers', '工作流'], body: ' # CodeStable 深度解析:编排软件生命周期,而非编排 Agent ## 模块 0:核心摘要 (TL;DR) > **一句话核心**:CodeStable 是首个将 AI 编码工作流的建模对象从"Agent 怎么协作"翻转为"软件要素怎么组织"的框架——它管的不再是 Agent,而是需求、架构、特性、问题、知识这六个实体的完整生命周期。 **认知挂钩**:想象你在管一个图书馆。SuperPowers 和 OpenSpec 在优化"管理员怎么工作得更高效"。CodeStable 在问一个更根本的问题——**书有没有被正确分类、编目、放在对的书架上**?管理员再高效,书是乱的,三年后谁也找不到东西。CodeStable 就是那个图书分类法。 **真理锚点**:*"软件工程的混乱本质上不是 Agent 不够强,而是要素没被组织好。"* —— liuzhengdong,CodeStable 作者 ## 模块 1:概念破冰 (Concept Ice-breaking) ### 巧记卡片 ``` AI 框架两派分: Agent 编排派 → 管的是"谁干什么、怎么配合" 软件要素派 → 管的是"需求架构特性问题知识,每样都放对位置" CodeStable 选了后者。记住6+3: 6 实体(Req, Arch, Roadmap, Feature, Issue, Compound) 3 流程(特性引入、问题修复、代码重构) ``` ### 故事引入 2026 年初,开发者 liuzhengdong 正在开发一套新的 Harness Agent(项目代号 MA)。一开始他用 VibeCoding——只写设计和需求,代码由 AI 改。这样撑了大部分特性开发。 直到有一天,Codex 反复解决不了一个"他认为比较简单"的问题,**反复在同一个地方犯错**。 他意识到:项目变大了,AI 开始迷失。不是因为 AI 不够聪明,而是因为**之前的那些需求、设计决策、架构约束,AI 全忘了**——或者更准确地说,这些信息散落在对话历史里,每次都丢失。 他调研了市面上所有的 AI 编码框架——OpenSpec、SuperPowers、Oh-My-OpenAgent——没一个让他满意: - OpenSpec "太简单,生成的 Spec 抽象到人类没法读" - SuperPowers "没有流程约束,不知道该用哪个" - Oh-My-OpenAgent "太重,且哲学上认为\'人介入 = 失败\'" 于是他决定从零写一套新的。2026 年 4 月,CodeStable 诞生。不到两个月,781 stars。 ### 可视化:两种范式的根本差异 ``` Agent 编排派(SuperPowers / OpenSpec / OMO): ┌─────┐ ┌─────┐ ┌─────┐ │Agent1│←→│Agent2│←→│Agent3│ ← 编排的是 Agent └─────┘ └─────┘ └─────┘ ↓ ↓ ↓ [代码] [代码] [代码] ← 软件要素在对话中丢失 软件要素派(CodeStable): ┌──────────┐ ┌──────────┐ ┌──────────┐ │Requirement│ │Architecture│ │ Feature │ ← 编排的是软件要素 └──────────┘ └──────────┘ └──────────┘ ↑ ↑ ↑ └────────────┼────────────┘ │ [Agent 们] ← Agent 是执行体,不是建模对象 │ codestable/ ← 所有产物持久化在文件系统 ``` ## 模块 2:深度解析 (Deep Analysis) ### 2.1 哲学内核:为什么"人在环"不是弱点而是设计选择 CodeStable 最受争议的点,也是它与主流框架最根本的分歧:**它认为程序员必须是"在环对象"**。 这个立场需要放在 2026 年的大背景下来理解。2026 年 2 月,Hashicorp 联合创始人 Mitchell Hashimoto 提出了 **Harness Engineering(驾驭工程)** 概念,核心哲学是"人类掌舵,Agent 执行"(Human Steer, Agent Execute)。很快,OpenAI、Anthropic、LangChain 等主流 AI 工具都采纳了这一范式。 CodeStable 可以理解为 Harness Engineering 在"编码工作流"这个细分领域的具体实现。它不是反对自动化——它反对的是**不留下痕迹的自动化**。 当你让 AI 自主完成一个 feature,对话结束后,你得到的是代码。但你失去了: - 为什么要这么设计? - 当时有哪几种备选方案? - 这个设计依赖了哪些约束? 三个月后,另一个 developer(或三个月后的你)面对这段代码时,这些信息全部丢失了。 CodeStable 的回答是:**每做一个决定,就在 `codestable/` 目录里写下来。** 不是给 AI 写的 prompt,是给人读的文档。 ### 2.2 6 个实体:软件要素的建模 这是 CodeStable 区别于所有其他框架的核心设计: ```mermaid flowchart TD CS["cs 根入口"] --> ONBOARD["cs-onboard 初始化"] ONBOARD --> REQ["cs-req: 需求实体"] ONBOARD --> ARCH["cs-arch: 架构实体"] REQ --> ROADMAP["cs-roadmap: 路线图实体"] ARCH --> ROADMAP ROADMAP --> FEAT["cs-feat: 特性流程"] ROADMAP --> ISSUE["cs-issue: 问题流程"] ROADMAP --> REFACTOR["cs-refactor: 重构流程"] FEAT --> FEAT_D["cs-feat-design"] FEAT_D --> FEAT_I["cs-feat-impl"] FEAT_I --> FEAT_A["cs-feat-accept"] ISSUE --> ISSUE_R["cs-issue-report"] ISSUE_R --> ISSUE_A["cs-issue-analyze"] ISSUE_A --> ISSUE_F["cs-issue-fix"] FEAT_A --> COMPOUND["compound: 知识沉淀"] ISSUE_F --> COMPOUND REFACTOR --> COMPOUND COMPOUND --> LEARN["cs-learn: 经验"] COMPOUND --> TRICK["cs-trick: 模式"] COMPOUND --> DECIDE["cs-decide: 决策"] COMPOUND --> EXPLORE["cs-explore: 探索"] LEARN -. "下次被检索" .-> ARCH TRICK -. "下次被检索" .-> FEAT_D DECIDE -. "下次被检索" .-> ISSUE_A EXPLORE -. "下次被检索" .-> ROADMAP ``` **实体 1:需求 (Requirement)** — 代码烂掉的最终逃生通道。需求文档保留了"为什么要有这个能力"的原始上下文。如果某个 feature 的实现彻底腐化了,你可以拿着需求文档让 AI 重新生成代码。 **实体 2:架构 (Architecture)** — "系统的编排层长什么样"。刻意强调**给人读的**,不是给 AI 自嗨的。这回应了作者对 OpenSpec 的批评——"生成的 Spec 抽象到人类没法读"。 **实体 3:路线图 (Roadmap)** — 大需求的拆解层。作者注意到一个关键问题:"我想要一个权限校验系统"直接塞给 AI 是接不住的。必须先拆成模块 → 子 feature → 分配执行顺序。这是人在环中起核心作用的一层。 **实体 4:特性 (Feature)** — 实际落地的执行过程。design → impl → accept 三步闭环,design 是后续所有步骤的**唯一输入**。这种设计避免了 AI 在实现过程中"自己脑补"需求。 **实体 5:问题 (Issue)** — Bug 单,report → analyze → fix 三步走。关键创新是**analyze 和 fix 分离**——AI 常常急于修复而不理解根因,强制分开让每次修复都有理论依据。 **实体 6:知识 (Compound)** — CodeStable 最核心的差异优势。四种知识类型覆盖了软件工程中所有"值得记录"的时刻:经验 (learning)、模式 (trick)、决策 (decision)、探索 (explore)。这些知识会在下一次 `cs-arch`、`cs-feat-design`、`cs-issue-analyze` 时被自动检索。 ### 2.3 分层架构:不是流水线,是"分层 + 事件驱动" CodeStable 的工作流不是一条线性流水线。它被组织成**5 层**: | 层 | 内容 | 触发时机 | |----|------|---------| | **阶段 0** | cs-onboard 初始化 `codestable/` 骨架 | 新项目接入时(一次) | | **第 1 层** | cs-req / cs-arch 长效档案 | 需求和架构变更时(反复刷新) | | **第 2 层** | cs-roadmap 规划层 | 大需求拆解时(按需进入) | | **讨论入口** | cs-brainstorm 分诊 | 想法模糊时(可选) | | **第 3 层** | cs-feat-* / cs-issue-* / cs-refactor-* | 事件驱动(来什么走什么) | | **横切层** | cs-learn / cs-trick / cs-decide / cs-explore | 任何时候觉得"值得记下来" | **关键设计洞察**:第 1 层和第 2 层刻意分开。"系统现在长什么样"和"接下来打算怎么走"是两个不同的问题。大部分 Spec 驱动框架把两者混在一个 Spec 文件里,导致"现状"和"规划"边界模糊。CodeStable 的解决方式是用不同的目录和不同的技能来管理。 ### 2.4 运行时结构:`codestable/` 目录设计 ``` 你的项目/ ├── codestable/ │ ├── requirements/ # 需求("为什么要有这个能力") │ ├── architecture/ # 架构("用什么结构实现") │ ├── roadmap/ # 路线图("接下来怎么走") │ ├── features/YYYY-MM-DD-{slug}/ # 特性执行 │ │ ├── {slug}-design.md # 方案(唯一输入) │ │ ├── {slug}-checklist.yaml # 清单(impl 跑、accept 回写) │ │ └── {slug}-acceptance.md # 验收报告 │ ├── issues/YYYY-MM-DD-{slug}/ # 问题修复 │ ├── refactors/YYYY-MM-DD-{slug}/ # 重构(beta) │ ├── compound/ # 知识沉淀 │ │ └── YYYY-MM-DD-{doc_type}-{slug}.md │ ├── tools/ # 共享脚本 │ └── reference/ # 共享参考文档 └── AGENTS.md ``` **三条设计原则**: 1. **所有产物聚在一个目录下** → "上次那个 feature 怎么搞的,三秒找到" 2. **日期前缀** → 按时间排序天然就是开发历史 3. **compound 用 type 字段区分而非分目录** → 方便跨类型搜索 ### 2.5 硬约束:Skill 隔离与跨 Skill 共享 CodeStable 有一个重要的工程约束:**每个 skill 运行时只能看到自己包内的文件**。这意味着 SKILL.md A 不能直接引用 B 的 reference 文件。 解决方案:`cs-onboard` 在初始化时从技能包**复制**共享文档到项目的 `codestable/reference/`,其他 skill 通过项目相对路径读取。 这本质上是一个**依赖注入**模式——技能是通用逻辑,`codestable/` 是注入的运行时上下文。和我们在 mattpocock/skills 中看到的 `setup-matt-pocock-skills` 设计如出一辙。 ## 模块 3:深度裂变 (Deep Fission) ### 🔍 "编排软件要素"是真的范式创新,还是旧酒新瓶? 这是对 CodeStable 最尖锐的批判性审视。 **正方:确实在范式层面做了翻转** 所有主流 AI 编码框架(截至 2026 年 5 月)都在"Agent 编排"这个范式下工作。它们回答的问题是:"Agent 之间怎么分工?怎么协调?怎么传递上下文?"CodeStable 问的是另一个问题:"软件的需求、约束、决策怎么被记下来、被检索、被复用?" 这个翻转在实践层面有一个直接后果:**知识沉淀从"副作用"变成了"一等公民"**。在 SuperPowers 中,你跑完一个 TDD 循环,你得到的是代码和测试。在 CodeStable 中,你跑完一个 feature,你得到的是代码 + design 文档 + acceptance 报告 + (可选的)compound 知识条目。后者在"三个月后还能被理解"这个维度上有结构性优势。 **反方:有四个没有解决的问题** 1. **知识检索依赖 AI 的上下文窗口**。compound/ 目录里的文件再多,最终还是要靠 AI "读" 来检索。如果 compound 积累了 200 个文件,AI 能一次读完吗?CodeStable 目前依赖 AI 在启动时选择性读取相关文件,没有真正的索引或向量检索。 2. **没有强制执行机制**。SuperPowers 的 TDD 是铁律——你跳过 RED 阶段,它直接中断你。CodeStable 的 `cs-feat-accept` 是验收,但验收的执行深度取决于你。如果人把关不严,整个质量门形同虚设。 3. **cs-brainstorm 的"分诊"能力受限于模型理解能力**。让 AI 判断一个模糊想法"该走 design 还是进 roadmap 还是直接 feature"——这个判断本身就需要很高的理解力。模型理解错了,整个流程从一开始就偏了。 4. **对比并非完全公平**。OpenSpec 的 Spec 文件设计目标就是**机器和人双读**,作者批评它"抽象到人类没法读",但很多 OpenSpec 用户的实际体验并非如此。这可能更多是使用方式和配置问题,而非框架本身的设计缺陷。 🔍 **搜索内化**:根据 V2EX 和 LINUX DO 社区讨论,CodeStable 的实际用户反馈总体积极——"正确性对我来说够了,按照流程生成完,手动审查,不复杂的需求基本一次性搞定"——但用户也指出了"上下文一长就会忘"的知识检索问题。CodeStable 作者在 README Roadmap 中也坦承项目处于早期阶段,多个模块(如 `cs-refactor`)仍在 beta。 ### 🔍 一个被忽略的关键信号:CodeStable 承认自己会"过时" 在 README 的 Roadmap 部分,有这样一句话: > "CodeStable 会根据模型能力的发展进行调整。如果未来某个模型做到某个模块的稳定产出,那么这个模块就可以删除。" 这让 CodeStable 区别于绝大多数 AI 框架——它不是试图建立一个永恒的体系,而是**承认自己是一个过渡性工具**。当未来的 AI 模型强到不需要手工组织软件要素时,CodeStable 的使命就完成了。 这种"自我消解的诚实"在 AI 工具领域极为罕见。大多数框架在讲"未来五年"的故事。CodeStable 在讲"在 AI 还不够好的当下,这样工作最舒服"。 ## 模块 4:实战指南 (Actionable Guide) ### 4.1 如何开始 ```bash # 安装 npx skills add https://github.com/liuzhengdongfortest/CodeStable # 初始化项目 /cs-onboard # 日常使用——不知道用哪个就喊根入口 /cs ``` ### 4.2 典型工作流 **场景 A:新增功能** ``` /cs-feat # 进入特性流程 /cs-feat-design # 写 design 文档(后续的唯一输入) /cs-feat-impl # 按 design 推进写代码 /cs-feat-accept # 对照 design 验收 ``` **场景 B:修 Bug** ``` /cs-issue # 进入问题流程 /cs-issue-report # 落成可复现的 report /cs-issue-analyze # 找根因、评估风险 /cs-issue-fix # 定点修复 + 验证 ``` **场景 C:快速小改动** ``` /cs-feat-ff # 超轻量通道,跳过 design/accept ``` **场景 D:沉淀知识** ``` /cs-learn # 踩坑经验 /cs-trick # 可复用模式 /cs-decide # 技术决策 ``` ### 4.3 避坑指南 | 🔴 反模式 | ✅ 正确做法 | |-----------|-----------| | 跳过 cs-onboard,手动创建 codestable/ 目录 | 必须用 cs-onboard 初始化,确保 reference/ 被正确复制 | | cs-feat-impl 中不看 design 自己脑补 | design 是唯一输入,偏离 design 必须回退更新 design | | 所有改动都走 cs-feat(太重) | 小改动用 cs-feat-ff,大功能走完整流程 | | compound 文件乱命名 | 严格遵循 `YYYY-MM-DD-{type}-{slug}.md` 格式,好搜 | | 不写 acceptance 报告 | cs-feat-accept 的验收报告是"三个月后能理解"的关键 | ### 4.4 CodeStable 与你现有工作流的融合点 如果你已经有 `/dev-flow`(openspec + grill-with-docs + zoom-out + apply + diagnose),CodeStable 可以和它互补使用: | dev-flow 阶段 | CodeStable 替代/增强 | |--------------|---------------------| | Phase 0 初始 PRD | `cs-req` 沉淀为需求文档(更持久) | | Phase 1.5 结构化 PRD | `cs-feat-design` 作为 design 文档 | | Phase 2 grill-with-docs | `cs-brainstorm` 作为讨论入口 | | Phase 2.5 zoom-out | `cs-arch` 单独维护架构文档 | | Phase 3 执行 | `cs-feat-impl` + `cs-feat-accept` | | Phase 4 收尾 | `cs-learn` / `cs-decide` 沉淀知识(比 CONTEXT.md 更结构化) | **关键差异**:dev-flow 的产出散落在 `docs/` 和 `CONTEXT.md` 中。CodeStable 的产出全部集中在 `codestable/` 下,用统一的命名约定管理。如果你的项目预计跨年维护,这种集中管理会越来越有价值。 ### 4.5 ROI 分析 | 投入 | 产出 | |------|------| | cs-onboard 初始化:2 分钟 | 建好所有目录骨架和共享 reference | | 跑完一个 feature 流程:比原来 OpenSpec 多 5-10 分钟 | 留下 design + acceptance + 可选的 compound,三个月后可回溯 | | 学习 22 个技能:30-45 分钟 | 覆盖需求→架构→特性→问题→重构→知识的完整链路 | ## 模块 5:温故知新 (Consolidation) ### 常见陷阱 (FAQ) <details> <summary><strong>Q: CodeStable 和 dev-flow 谁更好?</strong></summary> 不是替代关系。dev-flow 是流程编排元技能("按什么步骤走"),CodeStable 是一套完整的软件生命周期建模体系("软件要素怎么组织")。可以组合使用:dev-flow 的 grill-with-docs 补充 CodeStable 缺少的"术语对齐"阶段;CodeStable 的 compound 补充 dev-flow 缺少的"结构化知识沉淀"。 </details> <details> <summary><strong>Q: CodeStable 适合一个人用吗?</strong></summary> 非常适合。CodeStable 的设计前提就是"一个人在环"——没有团队角色、没有多 Agent 协作、没有审批流。它帮助单人开发者维持跨时间的一致性。如果是一个人维护的长期项目,CodeStable 是目前最合适的框架。 </details> <details> <summary><strong>Q: CodeStable 和 SuperPowers 能一起用吗?</strong></summary> 理论上可以,但不推荐。两者的哲学是对立的——SuperPowers 希望人少介入,CodeStable 要求人在环。同时用会导致认知冲突:"这一步到底是让 AI 自己决定,还是我来把关?"建议根据项目类型选一个主线。 </details> <details> <summary><strong>Q: codestable/ 目录会变得很臃肿吗?</strong></summary> 会。这是有意为之。作者认为"臃肿"的文档目录好过"干净"的失忆。每个 feature 都留下完整的 design + acceptance,长期积累确实会很多文件。但日期前缀命名使按时间浏览很自然,且 compound 通过 type 字段做聚合。 </details> <details> <summary><strong>Q: 轻量通道 cs-feat-ff 什么时候用?</strong></summary> 当你有一个非常明确的小改动——比如"把这个按钮的颜色改成蓝色"、"加一个表单字段"——不需要写 design 文档和完整的 acceptance 报告。但作者的建议是:"如果不确定该不该走 ff,就走完整流程"。 </details> <details> <summary><strong>Q: 如果我不想用全部 22 个技能怎么办?</strong></summary> CodeStable 的技能是松耦合的。你可以只用 cs-req + cs-feat-* 做特性开发,跳过 cs-roadmap 和 cs-refactor。最精简的子集:cs-onboard + cs-req + cs-feat + cs-issue。 </details> <details> <summary><strong>Q: CodeStable 的 knowledge 检索能力有多强?</strong></summary> 目前是"文件命名约定 + AI 选择性读取"模式,而非向量语义检索。当 compound/ 积累到 50+ 个文件后,AI 可能无法一次读完所有文件,需要在 prompt 中引导 AI 只读相关的。作者在 Roadmap 中表示关注这个问题。 </details> <details> <summary><strong>Q: 和 mattpocock/skills 的关系?</strong></summary> 同样是 Agent Skills 的封装形式,但建模哲学完全不同。mattpocock 的技能是"小工具"——每个技能解决一个特定问题(grill、diagnose、tdd)。CodeStable 的技能是"体系"——每个技能是软件生命周期中的一个步骤。前者灵活可组合,后者完整有体系。 </details> ### 自测题 1. CodeStable 的 6 个软件实体是哪 6 个?每个的核心用途是什么? 2. "编排 Agent"和"编排软件要素"的根本区别是什么?这种区别在工程实践上会产生什么不同的后果? 3. CodeStable 的 3 个核心流程分别是什么?每个流程的技能链是什么? 4. `cs-feat-design` 为什么被设计为"后续所有步骤的唯一输入"?这种设计避免了什么问题? 5. `compound/` 目录下的 4 种知识类型分别是什么?它们会在什么时机被 AI 重新检索? 6. CodeStable 为什么要求每个 skill 运行时只能看到自己包内的文件?这个硬约束解决了什么问题? 7. CodeStable 作者所说的"复利工程"(Compound Engineering)具体指什么? 8. 如果你要将 CodeStable 集成到你现有的 dev-flow 中,哪些 Phase 可以保留、哪些可以用 CodeStable 替换? ### 参考资源 - GitHub 仓库:https://github.com/liuzhengdongfortest/CodeStable - 作者的项目 MA:https://github.com/liuzhengdongfortest/MA - Harness Engineering 概念起源(Mitchell Hashimoto, 2026.02) - V2EX 讨论帖:https://global.v2ex.co/t/1208525 *© 2026 叫我小杨同学的小码酱 | 知识吸收器 v3.0 | 真理锚定已通过* ' },
|
||
];
|
||
|
||
// ---- Init ----
|
||
(function(){
|
||
document.getElementById('entry-count').textContent = ENTRIES.length;
|
||
document.getElementById('gen-time').textContent = new Date().toLocaleString('zh-CN');
|
||
|
||
if(ENTRIES.length === 0){
|
||
document.getElementById('entries').innerHTML = '<div class="no-results visible">暂无知识条目。<br>运行 /knowledge-absorber 学习新内容后,执行 bash scripts/update-knowledge-index.sh 重建索引。</div>';
|
||
return;
|
||
}
|
||
|
||
buildTagCloud();
|
||
buildYearFilter();
|
||
renderEntries(ENTRIES);
|
||
bindSearch();
|
||
bindYearFilter();
|
||
bindClearFilters();
|
||
})();
|
||
|
||
// ---- Tag Cloud ----
|
||
function buildTagCloud(){
|
||
const map = {};
|
||
ENTRIES.forEach(e => {
|
||
(e.tags||[]).forEach(t => {
|
||
if(!t) return;
|
||
map[t] = (map[t]||0)+1;
|
||
});
|
||
});
|
||
const sorted = Object.entries(map).sort((a,b)=>b[1]-a[1]);
|
||
const cloud = document.getElementById('tag-cloud');
|
||
cloud.innerHTML = sorted.map(([tag,count]) =>
|
||
'<span class="tag-badge" data-tag="'+escHtml(tag)+'">'+escHtml(tag)+'<span class="count">('+count+')</span></span>'
|
||
).join('');
|
||
|
||
cloud.querySelectorAll('.tag-badge').forEach(b => {
|
||
b.addEventListener('click', function(){
|
||
this.classList.toggle('active');
|
||
applyFilters();
|
||
});
|
||
});
|
||
}
|
||
|
||
function buildYearFilter(){
|
||
const years = Array.from(new Set(ENTRIES.map(e => (e.date||'').slice(0,4)).filter(y => /^\d{4}$/.test(y)))).sort((a,b)=>b.localeCompare(a));
|
||
const select = document.getElementById('year-filter');
|
||
if(!select) return;
|
||
select.innerHTML = '<option value="">全部年份</option>' + years.map(y => '<option value="'+escHtml(y)+'">'+escHtml(y)+'</option>').join('');
|
||
}
|
||
|
||
function bindYearFilter(){
|
||
const select = document.getElementById('year-filter');
|
||
if(select) select.addEventListener('change', applyFilters);
|
||
}
|
||
|
||
function bindClearFilters(){
|
||
const button = document.getElementById('clear-filters');
|
||
if(button) button.addEventListener('click', clearFilters);
|
||
}
|
||
|
||
function clearFilters(){
|
||
const input = document.getElementById('search-input');
|
||
const yearFilter = document.getElementById('year-filter');
|
||
if(input) input.value = '';
|
||
if(yearFilter) yearFilter.value = '';
|
||
document.querySelectorAll('.tag-badge.active').forEach(b => b.classList.remove('active'));
|
||
applyFilters();
|
||
}
|
||
|
||
// ---- Render ----
|
||
function renderEntries(entries){
|
||
const container = document.getElementById('entries');
|
||
if(entries.length === 0){
|
||
document.getElementById('no-results').classList.add('visible');
|
||
container.innerHTML = '';
|
||
return;
|
||
}
|
||
document.getElementById('no-results').classList.remove('visible');
|
||
|
||
container.innerHTML = entries.map(e => {
|
||
const dateStr = e.date ? e.date.slice(0,4)+'-'+e.date.slice(4,6)+'-'+e.date.slice(6,8) : '';
|
||
const tagsHtml = (e.tags||[]).filter(Boolean).map(t =>
|
||
'<span class="mini-tag" data-tag="'+escHtml(t)+'">'+escHtml(t)+'</span>'
|
||
).join('');
|
||
const related = findRelated(e);
|
||
const relatedHtml = related.length > 0 ?
|
||
'<div class="related-section"><div class="related-label">相关内容:</div>'+
|
||
related.map(r => '<a onclick="scrollToEntry(\''+escHtml(r.slug)+'\')">'+escHtml(r.title)+'</a>').join('')+
|
||
'</div>' : '';
|
||
const bodyPreview = (e.body||'').slice(0,300);
|
||
|
||
const entryHref = (e.path || ('knowledge_'+e.date+'_'+e.slug)) + '/'+(e.path || ('knowledge_'+e.date+'_'+e.slug)).split('/').pop()+'.html';
|
||
|
||
return '<div class="entry-card" data-slug="'+escHtml(e.slug)+'" data-title="'+escHtml(e.title)+'" data-tags="'+escHtml((e.tags||[]).join(','))+'">'+
|
||
'<div class="entry-header">'+
|
||
'<a class="entry-title" href="'+escHtml(entryHref)+'">'+escHtml(e.title)+'</a>'+
|
||
'<span class="entry-date">'+dateStr+'</span>'+
|
||
'</div>'+
|
||
'<div class="entry-meta">作者:'+escHtml(e.author||'unknown')+'</div>'+
|
||
(tagsHtml ? '<div class="entry-tags">'+tagsHtml+'</div>' : '')+
|
||
'<div class="entry-body">'+escHtml(bodyPreview)+(e.body&&e.body.length>300?' ...':'')+'</div>'+
|
||
relatedHtml+
|
||
'</div>';
|
||
}).join('');
|
||
|
||
// Bind mini tag clicks
|
||
container.querySelectorAll('.mini-tag').forEach(mt => {
|
||
mt.addEventListener('click', function(e){
|
||
e.stopPropagation();
|
||
const tag = this.dataset.tag;
|
||
const badge = document.querySelector('.tag-badge[data-tag="'+escHtml(tag)+'"]');
|
||
if(badge) badge.click();
|
||
});
|
||
});
|
||
}
|
||
|
||
// ---- Search ----
|
||
function bindSearch(){
|
||
const input = document.getElementById('search-input');
|
||
let debounceTimer;
|
||
input.addEventListener('input', function(){
|
||
clearTimeout(debounceTimer);
|
||
debounceTimer = setTimeout(applyFilters, 150);
|
||
});
|
||
}
|
||
|
||
function applyFilters(){
|
||
const term = (document.getElementById('search-input').value||'').toLowerCase().trim();
|
||
const selectedYear = (document.getElementById('year-filter')?.value||'').trim();
|
||
|
||
// Active tags
|
||
const activeTags = new Set();
|
||
document.querySelectorAll('.tag-badge.active').forEach(b => activeTags.add(b.dataset.tag));
|
||
|
||
let filtered = ENTRIES;
|
||
|
||
// Year filter
|
||
if(selectedYear){
|
||
filtered = filtered.filter(e => (e.date||'').slice(0,4) === selectedYear);
|
||
}
|
||
|
||
// Tag filter
|
||
if(activeTags.size > 0){
|
||
filtered = filtered.filter(e => (e.tags||[]).some(t => activeTags.has(t)));
|
||
}
|
||
|
||
// Search filter
|
||
if(term.length > 0){
|
||
const words = term.split(/\s+/);
|
||
filtered = filtered.filter(e => {
|
||
const haystack = ((e.title||'')+' '+((e.tags||[]).join(' '))+' '+(e.body||'')).toLowerCase();
|
||
return words.every(w => haystack.includes(w));
|
||
});
|
||
}
|
||
|
||
renderEntries(filtered);
|
||
|
||
// Highlight in filtered results
|
||
if(term.length > 0){
|
||
highlightMatches(term);
|
||
}
|
||
|
||
// Highlight matching tags
|
||
highlightMatchingTags(term, activeTags);
|
||
}
|
||
|
||
function highlightMatches(term){
|
||
const words = term.split(/\s+/).filter(Boolean);
|
||
document.querySelectorAll('.entry-title,.entry-body').forEach(el => {
|
||
let html = el.textContent;
|
||
words.forEach(w => {
|
||
const re = new RegExp('('+w.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')+')','gi');
|
||
html = html.replace(re, '<mark>$1</mark>');
|
||
});
|
||
el.innerHTML = html;
|
||
});
|
||
}
|
||
|
||
function highlightMatchingTags(term, activeTags){
|
||
document.querySelectorAll('.mini-tag').forEach(mt => {
|
||
const tag = mt.dataset.tag||'';
|
||
const matchesSearch = term.length > 0 && tag.toLowerCase().includes(term);
|
||
const isActive = activeTags.has(tag);
|
||
mt.classList.toggle('match', matchesSearch || isActive);
|
||
});
|
||
}
|
||
|
||
// ---- Related Content ----
|
||
function findRelated(entry){
|
||
const myTags = new Set((entry.tags||[]).filter(Boolean));
|
||
if(myTags.size === 0) return [];
|
||
return ENTRIES.filter(e => e.slug !== entry.slug && (e.tags||[]).some(t => myTags.has(t))).slice(0,3);
|
||
}
|
||
|
||
function scrollToEntry(slug){
|
||
const card = document.querySelector('.entry-card[data-slug="'+slug+'"]');
|
||
if(card){
|
||
card.scrollIntoView({behavior:'smooth',block:'center'});
|
||
card.style.boxShadow = '0 0 0 3px #3b82f6';
|
||
setTimeout(()=>{card.style.boxShadow='';},2000);
|
||
}
|
||
}
|
||
|
||
// ---- Utils ----
|
||
function escHtml(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');}
|
||
</script>
|
||
</body>
|
||
</html>
|