Ghost 代码库文档规范:在 Monorepo 中编写、同步与校验代码库指南
Ghost 的开源代码库文档(Codebase Documentation)面向所有希望理解、修改、测试并发布本仓库的开发者与自动化 Agent,说明"如何理解、改动、测试与发布"代码,并且与它所描述的代码一同公开、一起被代码评审。本文以 docs/contributing/documentation.md 为主线,结合 Ghost monorepo 的根 AGENTS.md、CONTEXT-MAP.md、package.json 中的文档校验脚本,系统讲解在 Ghost 仓库中为文档选择归属位置、编写原则、公共与私有内容隔离、人与 Agent 指南同步,以及提交前验证的完整工作流。读完你可以掌握一套可直接复制的多仓库文档治理方案。
为文档选择正确的"家":一个主题只保留一处权威内容
Ghost 文档的第一原则是 Give each topic one canonical home——每个主题只保留一处权威入口,其余地方一律用链接指向该来源,而不是把内容复制到多个文档面。其理由很直接:复制必然导致漂移,两处内容迟早不一致,而链接可以保证读者永远看到最新版本。
仓库为此给出了一张内容归属决策表,这是整个规范的核心骨架,必须完整保留:
| Content(内容类型) | Home(归属位置) |
|---|---|
| Codebase-wide setup, workflow, architecture, and practices(跨代码库的搭建、工作流、架构与实践) | /docs |
| Package, service, app, or test-suite details(包、服务、应用或测试套件细节) | A README beside the code(代码旁边的 README) |
| Canonical domain language(权威领域语言) | A CONTEXT.md beside the domain(领域旁边的 CONTEXT.md) |
| Relationships between bounded contexts(限界上下文之间的关系) | The root CONTEXT-MAP.md(根 CONTEXT-MAP.md) |
| Contribution policy and the contributor entry point(贡献政策与贡献者入口) | .github/CONTRIBUTING.md |
| Agent-only execution rules and constraints(仅面向 Agent 的执行规则与约束) | The nearest AGENTS.md or repository skill(最近的 AGENTS.md 或仓库技能) |
| Product, API, theme, and self-hosting documentation(产品、API、主题与自托管文档) | docs.ghost.org(官方产品文档站) |
围绕该表,规范补充了三条落地原则:
- 根 README 保持聚焦:根 README.md 只负责介绍 Ghost 并把贡献者引导到代码库文档,而不是承载大量细节。
/docs只放跨工作区或跨领域的指引:这正是 docs/README.md 的定位——它充当整个代码库文档的索引(Quick Start、Repository Structure、Guides 三部分),把跨系统话题(如 monorepo-structure.md、configuration.md)收拢起来。- 包或服务细节与代码放在一起:细节留在代码旁的 README,需要时再从概览链接过去。
以实际仓库对照这张表:跨系统指南位于 docs/codebase/(运行时架构、认证、数据库、Stripe 流程等)与 docs/contributing/(贡献类指南);而各 app 的自述如 apps/admin/README.md、apps/portal/README.md 就放在代码旁边。这种"概览在 /docs、细节在代码旁"的双层结构,正是"Give each topic one canonical home"的具体体现。
Context Files:为限界上下文建立权威术语表
CONTEXT.md 是一个限界上下文(bounded context)的词汇表,只记录三件事:该领域的重要术语、术语的精确含义、以及需要避免使用的词语。它的作用是把"领域语言"固化下来,避免团队与 Agent 在不同文档中各自发明同义词。
规范同时给出了边界约束:
- 架构与实现细节不要写进
CONTEXT.md,应放在附近的 README 或合适的代码库指南中; - 每个限界上下文及其关系都要登记到根
CONTEXT-MAP.md。
仓库中现存的四个 CONTEXT.md 可以直观印证该模式:
- apps/portal/CONTEXT.md —— 面向访客的会员组件 Portal(注册、登录、订阅结账、账户管理等)的术语定义;
- ghost/core/core/server/services/gifts/CONTEXT.md —— Gift Subscriptions(付费礼品订阅从购买到兑换、过期、消费、延续为付费订阅);
- ghost/core/core/server/services/gift-links/CONTEXT.md —— Gift Links(单个受保护文章/页面的可分享访问,不创建会员);
- ghost/core/core/server/services/email-service/CONTEXT.md —— Newsletter Email Sending(订阅邮件向邮件服务商的准备与提交)。
而根 CONTEXT-MAP.md 则是这些限界上下文的索引与关系图:它先列出每个 Context 的路径与一句话定义,再在 Relationships 一节用箭头写明上下文之间的依赖,例如 Portal ↔ Gift Subscriptions(Portal 呈现礼品订阅的购买与兑换旅程)、Gift Subscriptions ↔ Gift Links(两者兑换语义的差别)。新增一个限界上下文时,必须同时更新这里的关系描述。
谁应当更新文档:改代码的人就是文档责任人
规范给出一个简洁而强制的责任归属:
Whoever changes or introduces a documented concept is responsible for updating its documentation.
具体操作要求是:
- 在同一个 Pull Request 中更新文档,与它所描述的代码、工作流、命令或行为一起提交,而不是事后补文档或让别人"以后发现";
- 当改动跨越 README、
/docs与 agent 指引等多个层面时,逐层检查最近的 README、/docs以及 Agent 指南是否受影响; - 当读者既需要概览又需要深入指南时,两者都要更新;
- 涉及专业领域的内容,可以让受影响区域的负责人评审专门指南,但不能把文档工作留给他们事后去发现。
这套规则本质上把"文档"与"代码"视为一次改动的两个不可分割产物,从流程上消灭了"代码合了、文档忘了"的常见问题。
为当前代码库写作:务实、可验证、单一权威
写作层面的要求聚焦于"文档永远要匹配当前真实代码":
- 对照当前代码、脚本、测试与配置核验指南内容,不要凭记忆写作;
- 在可行时实际运行或验证命令与路径;
- 只保留一个权威答案,其他文档一律链接过去而非复制;
- 使用直接的语言、短小的章节、来自真实命令或代码的示例;
- 把关键信息放在概览里,然后用"For more detail"链接到聚焦的深入指南;
- 使用仓库相对链接,并且尽量链接稳定的文件或符号而不是易漂移的行号;
- 需要配图时,把公开安全(public-safe)的图片复制进仓库,不要使用会过期的 Notion 外链 URL。
这一节与 Ghost 的代码库文档形态完全吻合:例如 docs/contributing/development-setup.md 承担搭建概览,docs/contributing/testing.md 承担测试概览,而 docs/codebase/internal-caching.md 这类系统指南则负责深入讲解某一机制。
公开与私有指引严格分离
Ghost 的代码库文档是公开且对贡献者有用的,因此有一条红线:
- 绝不写入凭据、密钥、客户或站点数据、私有仓库细节、内部主机名、事故与运维流程;
- 在贡献者确实需要的地方记录公开集成边界,私有部署与运维内容留在内部工作区;
- 公开私有来源材料前先审查再提交("Never commit it and remove the sensitive parts later"),禁止先提交再回头删除敏感部分。
这条原则在 docs/README.md 的"Additional Resources"与 docs/ 各指南中都有体现:产品级 API、主题与自托管文档统一指向官方 docs 站点,仓库内文档只覆盖代码库本身的开发与贡献话题。
保持人类与 Agent 指南同步
随着 AI Agent 参与开源贡献,Ghost 明确了两类文档的分工与同步机制:
- 人类可读文档是"事实与约定的唯一真相来源"(source of truth),人与 Agent 共享同一套事实与约定;
AGENTS.md只负责两件事:指向权威文档的方向性指引(routing),以及 Agent 专属的执行约束(execution constraints);不要在其中重复人类文档的事实,避免两处内容再次漂移;- 仓库技能(repository skills)链接到权威指南,而不是把权威指南内容复制进技能文件;
- 在同一个 Pull Request 中同步更新人类文档与需要发现它的 Agent 入口;
- 每个被跟踪的
AGENTS.md不得超过 150 行,且该上限由文档 lint 强制检查。
根 AGENTS.md 是这条规则的绝佳范本:全文开头声明"Agent-specific execution guidance",随后只给出一组指向 docs/contributing/development-setup.md、docs/contributing/workflow.md、docs/codebase/monorepo-structure.md 的必读清单,以及"总是使用 pnpm""改包前先读最近的 AGENTS.md / CLAUDE.md / README"这类路由与约束,而不是重复事实。它把共享事实留给人类文档、把执行纪律留给自己,两者通过相对链接彼此咬合。
150 行上限的实现:源码级佐证
150 行约束并非纸面约定,而是有真实脚本强制的:查看 scripts/check-agent-guidance.js,其中定义 MAX_AGENT_GUIDANCE_LINES = 150,并通过 git ls-files -z ':(glob)**/AGENTS.md' 列出所有被 git 跟踪的 AGENTS.md,逐文件统计行数,超过上限即打印形如 xxx/AGENTS.md has 210 lines (maximum 150) 的错误并使进程以非零码退出。这意味着一个无法被审阅者发现的超长 AGENTS.md 会被 CI 直接拦截。
同理,仓库技能的发现机制也有脚本守护:scripts/check-agent-skill-links.js 校验 .agents/skills/<name>/SKILL.md 存在,且 .claude/skills/<name> 是指向 ../../.agents/skills/<name> 的正确符号链接,否则报错并提示修复命令。这与根 AGENTS.md 中"Repository skills live under .agents/skills/…Run pnpm lint:agent-skills to verify discovery"的说明一一对应。
提交前验证你的改动
规范为文档改动给出了一组强制检查命令:
pnpm check
pnpm lint:docs
git diff --check origin/main...HEAD
每条命令的职责如下:
pnpm check:仓库级卫生总检。查看根 package.json 可知它依次执行format:check(oxfmt 格式检查)、lint(含 lint:boundaries、lint:packages、lint:docs)与test,是全量验证的默认入口,与 docs/README.md 中"Usepnpm checkas the default one-stop command"一致。pnpm lint:docs:文档专属 lint。它在 package.json 中被定义为四个子任务的串联:lint:agent-skills(校验技能可发现性)、lint:agent-guidance(执行 150 行上限)、lint:markdown(用markdownlint-cli2跑 Markdown 风格检查)、lint:doc-links(用remark --use remark-validate-links --frail校验 Markdown 内链接有效性)。git diff --check origin/main...HEAD:以main为基线检查 diff 中的空白错误等格式问题。
同时规范给出三条人工复核要点,因为它们当前尚未被工具完全覆盖:
- 链接需要手动检查——
pnpm lint:docs目前并不校验 Markdown 链接指向的页面是否真实存在(remark-validate-links 只做语法与结构层面的校验),因此必须人工逐一确认; - 确认没有另一份文档给出不同的答案——即前文"单一权威答案"原则的最后防线;
- 确认没有私有或临时材料被公开——提交前再扫一遍内容;
- 迁移完成并上线后,替换指向其 Notion 源的链接并下架旧页面,避免出现指向过期来源的死链。
结语
Ghost 的代码库文档规范用一张内容归属决策表、一套 CONTEXT 与 AGENTS 文件约定、一组责任规则和三条校验命令,把"文档与代码一起评审、一起发布"变成可执行、可自动化的工程纪律。其要点可归纳为四条:一个主题只留一个权威来源(其余用链接)、改代码的人同步改文档(同一 PR 提交)、人类文档是共享事实源(AGENTS.md 只做路由与约束并遵守 150 行上限)、提交前用 pnpm check / pnpm lint:docs / git diff --check 验证。这套方法论既不绑定具体语言也不依赖特定工具链,任何希望让人与 Agent 在同一仓库中高效协作的团队,都可以直接从上述脚本与文件结构出发进行复制与落地。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python08
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00