Skip to content
miuiadminPublic

About

Curia MD — 可移植的文档管理方案:两根布局、9 类文档、3 行头块、零依赖检查器与脚手架,人与 AI agent 共用同一套读写规则。A portable documentation workspace for humans and AI agents: 9 doc types, 3-line headers, zero-dependency checker, scaffold.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

Curia MD

Curia 2.2 — 可移植的文档管理方案:两根布局、9 类文档、3 行头块、零依赖检查器与脚手架,人和 AI agent 按同一套规则读写。

简体中文 | English

License: MIT Node ≥ 18 Dependencies: 0

目录:是什么 · 适合谁 · 核心设计 · 装上去 · 跑完怎么确认装对了 · 采用到已有仓库 · 常见问题 · 维护这个包的人读这里

中文是默认语言,也是维护契约的权威版本;English 为逐节对照翻译,如有歧义以中文为准。

是什么

Curia 2.2 是一套可移植的文档管理方案:两根布局——.agents/ 管过程与制度(计划、调研、决策笔记、技能、归档),docs/ 管外部事实与知识;9 类文档各有家与骨架;类型化文档统一带 3 行头块;配 1 支零依赖检查脚本 check-docs.mjs(Node ≥ 18,不联网)。采用后,文档放哪、长什么样、怎么引用、过时了怎么退役,都有明文,人和 agent 按同一份规则读写。

create-curia 是它的本地分发包,也是一个生成器:把载荷复制进你的仓库、建好三条桥符号链接(CLAUDE.md、.claude/skills、.codex/skills——让 Claude Code、Codex 等 CLI 直接读到规则与技能)、打印下一步。它不提问、不装钩子、不运行载荷内任何脚本;一次跑完即 fork-and-own——生成后的文档树归你维护,本包没有 upgrade / check 驻留子命令。

要不要用,看两条:你想让项目的文档有固定归属、固定格式,且希望人和 agent 按同一套规则帮你写与查——用它;你在找流程引擎、门禁体系、审批流或权限模型——这些不在 Curia 里,规范开篇就写明它不是治理平台、流程引擎或门禁体系。上手成本低:有 Node ≥ 18 就跑生成器;没有也能用——直拷载荷、只采用文本约定(见「备选:直接拷贝」)。

适合谁

适合。

  • 多个会话(人 + Claude Code / Codex 等)同时写文档,开始出现「这份放哪、那份过时没有」的分歧。
  • 想让文档结构可机械检查,但不想引入平台、服务、数据库或 CI 依赖。
  • 接受 fork-and-own:拿走一份载荷,之后按自己的节奏维护。

不适合。

  • 需要审批流、权限模型、发布门禁、注册表或流程引擎——Curia 明确不提供这些。
  • 想找文档自动生成、迁移工具或批量修复——本包不做。
  • 团队还没有任何文档习惯,指望一套目录结构自动解决协作问题。

核心设计

两根布局,封顶两根

根 装什么 不装什么
.agents/ 过程与制度:计划、调研、决策笔记、技能、归档。 外部事实登记、面向最终读者的发布内容。
docs/ 知识与外部事实:仓外系统的登记与定义(资源 ID、字段映射、端点、协议);当前版即唯一真相,无状态机。 计划与提案、决策因果、原始事实快照。

受管面封顶这两根,不再设第三根;项目可以只启用其中一根。

四句口诀

  1. 没做的 → plans/(proposal / spec / plan)
  2. 做完的 → research/(survey / evidence / postmortem / reference)
  3. 为什么 → notes/(决策因果,永远不进 research)
  4. 过时的 → 状态翻转优先,冷历史进 archive/ 封存;永不删除

补:可复用的干法 → skills/(skill / runbook);外部事实 → 根 docs/。

9 类文档

Type 家 是什么 建议节
proposal plans/ 立项前对齐:为什么值得做、做成什么样算成功、有哪些候选路线。 背景、目标、成功判据、方案选项
spec plans/ 长期契约:做成什么样——字段、接口、验收标准;done 不是退役。 背景、范围、契约、验收标准、适用边界
plan plans/ 分几步做、做到哪了;active 时「未完成事项」是唯一活跃清单。 背景、步骤、未完成事项
survey research/ 一次性调研:问题、方法、结论与适用边界。 问题、方法与来源、结论、证据与出处、适用边界
evidence research/ 原始事实快照:什么时候、用什么命令、看到了什么。 采集内容、采集方式、适用边界
postmortem research/ 事故复盘:时间线、因果链、影响、预防与行动项。 事故概述、时间线、影响、因果链、预防、行动项
reference research/ 长期事实参考:持续维护的映射与导览。 事实映射、方法与来源、维护方式、适用边界
runbook skills/ 人向操作手册:前置条件、步骤、每步验证、失败恢复。 前置条件、步骤、验证、失败与恢复
skill skills/ Agent 按需加载的工作流:frontmatter 加步骤加边界。 步骤、边界

「建议节」是骨架默认,不是机器配额;检查脚本不查节的完整性。类型表是上界不是配额——短文档为主的项目可以删减类型与建议节。

3 行头块

类型化文档(plans/、research/、skills/ 家内的 Markdown)统一带固定三行,顺序不可换:

# <标题>

Type: <9 类之一>
Status: <该类型允许值>
Updated: yyyy-mm-dd

Status: superseded 必须带 Superseded-by: <相对链接>;归档件必须带 Archived: yyyy-mm-dd。笔记用两行头块(标题加 Status:),docs/ 无头块。完整规则见载荷内 .agents/README.md。

检查器

node .agents/tools/check-docs.mjs            # 报告模式:列发现,不失败
node .agents/tools/check-docs.mjs --strict   # 严格模式:任一发现即失败

只查机械子集:编码、头块与生命周期、家与命名、相对链接。零依赖、不联网、不执行文档内代码。检查通过不等于文档合规——节的完整性、事实真假、结论质量、时效新鲜度都不在机器判定面。

三条桥

生成器会建三条符号链接,让不同 CLI 读到同一份规则与技能:

桥 指向 谁读
CLAUDE.md AGENTS.md Claude Code
.claude/skills ../.agents/skills Claude Code
.codex/skills ../.agents/skills Codex

桥是指针,不藏内容;改规则只改 AGENTS.md 与 .agents/。

装上去

包里内容很少:bin/init.mjs(生成器)、template/(载荷,21 个文件加 3 条桥符号链接)、README.md、README.en.md、package.json、LICENSE——整个目录自足,拷到你机器上任意位置即可用,不需要网络与任何外部件。

前置只有一条:Node ≥ 18。用法如下(<包路径> 指包目录在你机器上的路径):

node <包路径>/bin/init.mjs --dir <目标仓路径>

不指定 --dir 时,目标是当前工作目录——也可以先 cd 进目标仓,再运行包内入口。参数只有三个:

  • --dir <path> — 目标目录。
  • --defaults — 兼容保留:init 无提问,等价默认行为。
  • -h, --help — 帮助与退出码。

一次运行做三件事:复制 21 个载荷文件(检查脚本 check-docs.mjs 与 7 个 .gitkeep 占位都在这 21 件之内)、按需创建三条桥符号链接、打印「下一步」。既有文件一律不覆盖——被保留的、被占用的都会在输出里写明,见「采用到已有仓库」。

装完后目标仓长什么样

<目标仓>/
├── AGENTS.md               # Curia 通用规则集(8 条)
├── CLAUDE.md               # -> AGENTS.md(桥)
├── .agents/
│   ├── README.md           # 规范全文(唯一权威,骨架文本在内)
│   ├── GLOSSARY.md         # 术语种子
│   ├── notes/AGENTS.md     # 笔记树入口(agent 原生读取)
│   ├── tools/check-docs.mjs
│   ├── plans/ research/ notes/ archive/   # 计划 / 调研 / 笔记 / 归档(各带 README 与 .gitkeep 占位)
│   └── skills/             # write-doc / write-note / prose-standard
├── .claude/skills          # -> ../.agents/skills(桥)
├── .codex/skills           # -> ../.agents/skills(桥)
└── docs/README.md          # 外部事实与知识的根约定(按需启用,见文件内说明)

这就是全部新增:21 个文件加 3 条桥。宿主已有同名文件时,那几件保持原样、不在此列。

备选:直接拷贝(没有 Node ≥ 18 时)

不跑生成器、把载荷原样拷过去也可以。源一定写 template/.——末尾的 /. 让 cp 连点目录一起拷;整目录拷进空仓即为可用工作区(21 个文件加 3 条桥链接):

cp -an template/. <目标仓>/

cp -R template/* 会静默漏掉 .agents/、.claude/、.codex/ 三个点目录——退出码 0、不报错,落出一个没有框架的树;不要用这种写法。cp -R(不带 -n)还会覆盖宿主的同名文件——包括未提交的改动与未跟踪的文件,那些字节在 git 历史里也找不回来。直拷一律带 -n,且拷之前先 git status 确认没有未提交内容。

直拷的短处是不报告跳过了什么:目标已有同名文件时 cp -an 静默跳过(实测 macOS 的 BSD cp 以退出码 1 结束、stderr 为空),三条桥可能静默缺失——所以直拷后不能只看退出码,务必按「跑完怎么确认装对了」把三条桥数一遍。目标仓已有自己的 AGENTS.md、CLAUDE.md 或 .claude/skills 时,优先用 init:它会逐条报告哪条桥没接上。

另外,直拷只对源码树形态成立:npm pack 出的 tarball 载荷里没有 3 条桥符号链接,拿到 tarball 就一律走 init(见「分发边界」)。

跑完怎么确认装对了

第一看退出码与汇总行。空仓上汇总行应当是:

完成:目标 <路径> — 新建 21、已一致 0、保留 0;桥 3 条:新建 3、已就位 0、未接上 0

退出码:

退出码 含义
0 载荷落地且三条桥全部接上
1 复制失败——I/O 出错、落点解析到目标仓之外(.agents/、docs/ 之类被预先做成指向仓外的符号链接)、或落点在另一个 git 仓里(.agents/ 是子模块或嵌套克隆)
2 用法与守卫(参数写错、目标落在包内、Node 版本不足等)
3 桥未接上——写操作完成但机制没接上

判据是退出码 0 与「未接上 0」这两项;汇总行里的「新建 / 已一致 / 保留」随宿主形状变(有主仓上「新建」不会是 21、「保留」不会是 0),别拿它们逐字对。

把 init 接进 CI 时:三条桥路径都空闲时退出码 0、流水线照常;宿主已有桥路径被占用时返回 3、流水线变红——接入前先按「采用到已有仓库」清障。注意:退出码 0 回答的是「没有复制失败、三条桥全部接上」——「保留 N 项」不改变它;宿主原有的 AGENTS.md 被保留时,8 条通用规则集并没有装上,见下一节。

第二,核对三条桥都接上了:

ls -l CLAUDE.md .claude/skills .codex/skills

三条都要在,且分别指向 AGENTS.md、../.agents/skills、../.agents/skills。光看 readlink 不够——要打开它:ls .claude/skills 应能列出 write-doc、write-note、prose-standard 三个技能目录。字符串对而打不开是可能的——父级目录(如 .claude)本身是指向仓外的符号链接时,链接会被建到仓外、按落点解析后悬空。init 现在按「真解析得到、且落在目标仓内」判定,所以它报「未接上」就是真没接上;这种形态下它也不会在仓外写任何东西。

第三,跑一次自检(在目标仓根):

node .agents/tools/check-docs.mjs --strict

退出码 0 即通过。判据是退出码,不是篇数——纯载荷树输出「检查 12 篇 / 告警 0 条」,你往 docs/ 放一份自己的文档就变 13 篇,篇数随你的树走。

第四,重跑幂等:对同一目标再跑一次 init,退出码应回到 0 且「未接上」为 0(空仓上是「新建 0、已一致 21、保留 0;桥 3 条:新建 0、已就位 3、未接上 0」;有主仓上数字随保留项变化)——重跑是安全的,已一致的文件会自动跳过。

采用到已有仓库

init 的原则是不覆盖既有文件——这对安全是好事,但意味着「退出码 0」不等于「一切都装上了」。逐种情况说清。

宿主已有自己的 AGENTS.md(真实宿主最常见)。 init 会保留它并列入「已存在且内容不同,未覆盖」,载荷里的 8 条通用规则集不会装入——三条桥照常接上,退出码仍可能是 0。规则集需自行并入:把包内 template/AGENTS.md 的「通用规则」「桥」「结构速览」三节一起并进你的 AGENTS.md(三节要同批并——「下一步」里让你补的项目名占位在「结构速览」里,只并「通用规则」会把那条指引指空)。核对一条就够:在你的 AGENTS.md 里搜「一事实一归属」(规则第 1 条)——搜不到就是没装上。并入之后,「已存在且内容不同,未覆盖」这条清单每次重跑都会照旧出现,属预期,不是没生效。

宿主已有 CLAUDE.md(真文件,不是桥链接)。 桥建不上,init 会逐条警告并具名列出,汇总退出码 3。做法:把它备份移走、内容并入 AGENTS.md,重跑 init(已一致的文件自动跳过)。桥的语义是 CLAUDE.md 成为 AGENTS.md 的指针——指针不藏内容。

宿主已有 .claude/skills 目录(或指向别处的链接)。 同样退出码 3。做法:把其中有用的技能内容迁入 .agents/skills/,备份移走占用路径,重跑 init。init 打印的手工命令形如 mv <路径> <路径>.pre-curia && ln -s <目标> <路径>,可直接照抄(先备份再建链,两条一起跑)。不要自己写裸的 ln -s <目标> <路径>:路径已是目录时,它会在目录里建出一个同名子链接、退出码 0,桥却没接上——静默假成功。

宿主根上 .claude 或 .codex 本身是指向仓外的符号链接(dotfiles 共享配置的常见形态)。这时相对目标 ../.agents/skills 会按落点解析到仓外、必然悬空,init 直接判「未接上」并说明父级解析到了哪里,不在仓外写任何东西。要接上得先决定那个符号链接的去留(删掉换真目录,或换一种暴露方式)。这是本包早期版本的又一个静默假成功:桥被建到仓外、readlink 字符串逐字正确、退出码 0、自检全绿,而桥是死的且根本不在仓里。

宿主已有 docs/README.md。 影响最小:它是 docs/ 的根约定,该目录按需启用、不启用也不影响 .agents/ 完整使用——并入与否都不挡路。

备份放哪。 没有约定:挑一个仓外位置(如 ~/.curia-backup-<日期>/)或仓内已被忽略的目录。init 不管备份,也不删你的任何东西——mv 那一步是你自己执行的。

宿主把 .agents/ 或 docs/ 预先做成了指向仓外的符号链接。 载荷会整份写到仓外、git 完全看不见——本包早期版本在这里报「完成」、退出码 0。现在落点按「上溯到最近的存在祖先再真解析」判定,落在仓外一律拦下、逐件具名、退出码 1,一个字节都不写到仓外(嵌套形态如 .agents/plans/ 指向仓外同样拦)。修法同样是先决定那些符号链接的去留,再重跑。

宿主把 .agents/ 做成了 git 子模块(或嵌套克隆)。 载荷会整份写进那个仓的工作树,宿主仓 git 永远追不到它(git add -A 只登记子模块指针)——而 init 会报「完成」。落点判据现已扩到 git 边界:落点在另一个 git 仓里一律拦下、逐件具名、退出码 1。做法:先决定 .agents 是留作子模块还是换成普通目录。

没有 Node ≥ 18 又有占用路径。 这一组合最麻烦:直拷不报告冲突、init 要 Node。出路是手工挑拣——把 template/ 下的载荷件逐件比对后拷进去,再手工补三条桥 ln -s。

宿主已有存量文档树要纳入 Curia。 纳入纪律(登记根、规则不回溯、闸门只挂默认面等六条)见规范「存量树只读纳管」节(目标仓 .agents/README.md,包内 template/.agents/README.md);本包不提供迁移工具与批量修复。

处理完任何一项,都用「跑完怎么确认装对了」的桥核对与自检收尾。

常见问题

它是运行时或平台吗? 不是。没有服务、数据库、网络调用、权限模型或审批流;检查器只做静态自检。

会覆盖我已有的文件吗? 不会。已有且内容不同的文件一律保留并列出;桥被占用时打印手工命令后跳过。

没有 Node ≥ 18 能用吗? 能。直拷 template/. 并手工补三条桥,或只采用文本约定、不跑检查器。

9 类文档必须全用吗? 不必。类型表是上界不是配额;可以删减类型与建议节,只保留你实际会写的。

生成后还能升级吗? 没有 upgrade 子命令。fork-and-own:重跑 init 到新目录做 diff,或 git cherry-pick。

能用在 monorepo 吗? 能。工作区根放在你希望管理的目录;默认扫描该根的 .agents/ 与 docs/,其他根用显式路径巡检。

检查器会改我的文件吗? 不会。只报不改,没有 --fix,从不写回文件。

维护这个包的人读这里

采用方读到这里就够了;以下各节讲这个包自身的契约、发布与验收。

本仓是 Curia MD 的公开母仓,独立于任何采用方发展。本仓只保留公开分发包所需的内容:规范、检查脚本、脚手架、双语 README 与元数据,不包含设计史料、研究笔记或内部实现记录。

红线

  • 生成器,不是运行时:init 只复制载荷、建桥与打印下一步——不提问、不装钩子、不运行载荷内任何脚本;生成物不 import 本包任何模块。
  • 零依赖:本包 dependencies 为空,只用 Node 内置模块(Node ≥ 18);载荷脚本同样零依赖、不联网。
  • fork-and-own:生成后目标仓与本包再无关系;没有 upgrade / check 驻留子命令,同步靠重开 init 到新目录 diff,或 git cherry-pick。
  • 不覆盖:目标已存在且内容不同的文件一律保留并列出;桥被占用时打印「先备份移走、再 ln -s」的手工命令后跳过。

版本纪律

package.json 的 version 是制品身份,不是依赖关系——包内任何文件的改动必须同批跳 patch 号,使「create-curia@<版本>」唯一对应一份字节。判据是制品不是载荷:只改本 README 也要跳号,因为 tarball 的字节变了。此前 0.3.0 曾跨三份不同字节(2.2 落地之后载荷又改过两次),「无损迁移」因此没有可核对的参照物;本纪律自 0.3.1 起生效。

发布制品时记下 shasum -a 512,采用方记一行「采用 create-curia@<版本>,sha512-…」即获得可复核的身份。发布前另跑一次核对(npm pack 丢符号链接是预期行为,不是错误):

npm pack --pack-destination <tmp>
tar -xzf <tmp>/create-curia-<版本>.tgz -C <tmp>
diff -rq <tmp>/package/template template    # 预期差异恰为 3 条桥(CLAUDE.md、.claude/skills、.codex/skills)

验收(维护方)

以下判据逐条可跑,验收对象是载荷自身,不构成采用方义务;check-docs 指载荷内 .agents/tools/check-docs.mjs。

  1. 空集断言:mkdir -p /tmp/empty-docs && node .agents/tools/check-docs.mjs --strict /tmp/empty-docs → 输出「未检查任何文件」,退出码 2。
  2. 正例:在载荷树(template/)或载荷生成的仓库里、于该树根下跑 node .agents/tools/check-docs.mjs --strict → 退出码 0。
  3. 根锚点断言:在自身不含 .agents/ 的目录里跑默认调用(如 cd /tmp && node <路径>/check-docs.mjs)→ 输出「根锚点缺失」,退出码 2,不静默降级、不向父目录上溯。
  4. 零依赖:rg -n "from ['\"]|require\(|import\(" template/.agents/tools/check-docs.mjs → 只应出现 node: 前缀的内置模块名。
  5. 可移植:把 .agents/ 拷进无 git、无 node_modules 的临时目录,跑 node .agents/tools/check-docs.mjs --strict → 与源目录同一判定。
  6. 桥断言:init 到空宿主 → 退出码 0、汇总行「桥 3 条:新建 3、已就位 0、未接上 0」,对同一空宿主重跑 → 「新建 0、已一致 21、保留 0;桥 3 条:新建 0、已就位 3、未接上 0」、退出码 0;init 到已有 CLAUDE.md 真文件的宿主 → 退出码 3 并具名列出未接上的桥(该宿主重跑仍为退出码 3——占用路径没清障前不会自己变好)。
  7. 退出码断言:node bin/init.mjs --bogus → 退出码 2;node bin/init.mjs --dir <包内路径> → 退出码 2;node bin/init.mjs --help → 退出码 0。
  8. 版本纪律目检(发布前,人工):git log -1 --stat 显示本仓有改动(template/、bin/、README.md 任一),而 package.json 的 version 未随之跳号 → 制品身份与字节脱钩,不许发布。
  9. 桥解析断言:init 到「.claude 是指向目标仓之外符号链接」的宿主 → 退出码 3、具名报出「父级目录……解析到目标仓之外」,且仓外那个目录零写入(前后 ls -A 计数不变)。
  10. 结构组假绿断言:造一棵只有 .agents/README.md 与 .agents/tools/check-docs.mjs、五个家(plans/ research/ notes/ skills/ archive/)一个都没有的树,跑默认调用 → 汇总行带「结构组无判定对象」(是标注,退出码仍按告警数走)。
  11. 面外类型化断言:把一份带 Type: plan 三行头块的文档放进 docs/、同内容放 .agents/plans/ → 组 2 只报 docs/ 里那份(「类型 plan 的文档住在 .agents/ 之外」),--strict 退出码 1。
  12. 落点断言:宿主把 .agents/(或 docs/,或嵌套的 .agents/plans/)预先做成指向仓外的符号链接 → init 退出码 1、逐件具名「落点……解析到目标仓之外」,且仓外那个目录零写入(前后 ls -A 计数不变)。
  13. git 边界断言:宿主把 .agents 做成 git 子模块 → init 退出码 1、逐件具名「在另一个 git 仓里」,且子模块工作树零写入。

分发边界

本包不分发到公共 registry,分发方式是源码入口、载荷直拷与发布制品(tarball,见「版本纪律」)三条。发布制品以 curia-v<版本> tag 与 tarball asset 的形态发布在本仓;本仓的公开分发从 create-curia@0.3.16(curia-v0.3.16)起,更早的版本与设计史料不随公开仓分发。package.json 的 private: true 是常设的防误发限制,不是待移除的过渡标记——不要移除它。

npm pack 会静默丢弃载荷里的 3 个桥符号链接(源载荷 3 条 → tarball 内 0 条,零 warning)——tarball 采用方一律走 init(建桥由桥步完成,不依赖载荷里的链接),或手工补三条 ln -s;从 tarball 直拷得到的是零桥工作区。

包名 create-curia 在公共 registry 无人占用,而机器默认指向公共源——一旦被抢注,npm create curia 会在配置如默认的机器上静默拉取并执行第三方代码。本包因此不宣传 npm create curia 这条用法(它在本包不发布的前提下本来也不可用)。repository 字段的占位值不影响使用。

许可

MIT,见 LICENSE。

About

Curia MD — 可移植的文档管理方案:两根布局、9 类文档、3 行头块、零依赖检查器与脚手架,人与 AI agent 共用同一套读写规则。A portable documentation workspace for humans and AI agents: 9 doc types, 3-line headers, zero-dependency checker, scaffold.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages