宪法

宪法

宪法的源文件在它的版目录 constitution/<YYYY-MM>/ 下,目前是 constitution/2026-10/:一个 index.toml,以及 articles/ 下每条一个目录。目录以版命名,草案获批准后也不改名;状态只记在 index.toml 里。工具把 constitution/ 下唯一一个含有 index.toml 的目录当作版目录,一个都没有或者不止一个时报错,所以工具里任何地方都不写这个目录名。

宪法由 uv run constitution-build 从这些源文件编译,它是 workspace 成员 tools/compiler (只用 Python 标准库)。它为 index.toml 里的每种语言向版目录的 generated/ 写两个文件:constitution.<lang>.md (完整版) 和 constitution.<lang>.agent.md (agent 版,见「agent 版」一节),两者都提交进仓库,从不手改;--check 不写任何文件,只运行检查,检查项见检查程序。

constitution/2026-10/
  index.toml
  articles/
    05-boundary-rule/
      article.toml
      01-must-ask.toml
      02-decide-yourself.toml
  generated/
    constitution.en.md  constitution.en.agent.md
    constitution.zh.md  constitution.zh.agent.md

index.toml:

  • status:在人第一次批准这份文本之前是 draft,之后是 active。
  • edition:这一版的名字,即委托人批准它生效的年月,YYYY-MM;必填。草案写它准备成为的那一版的名字,也就是计划批准的月份;如果在别的月份批准,届时给这一版改名。一版是一份完整的文本,就像以通过年份命名的宪法。制定新的一版本身就是一次修正案,需要委托人批准,而且一个月内至多制定一版,所以不会有两版同名;同一版内编号永不改变 (见「编号」一节),新的一版可以随意重新编号。
  • revision:一个字符串,即这一版内的修订号:草案是 0.<n>,每份草案 (第一版的和以后各版的) 的 <n> 都从 1 起算;一版第一次获批准的文本是 1,每采纳一次修正案就加一,新的一版重新从 1 起算。构建 manifest 会记下它。同一版内,宪法文字改了,修订号就增加;文字没改,修订号也不变 (检查程序,第 7 项检查)。
  • languages:语言代码,第一个是默认语言。每种语言在构建脚本里都必须有一条渲染条目 (一张表 LANGUAGES 存放所有因语言而异的内容:文件头,标题、编号和引用的形式,废止说明)。增加一种语言,就是在那里加一条条目,并给每张文本表加一个键。
  • [title]:标题,每种语言一行;构建在它后面加上版名 (见「编号」一节)。
  • [front]:标题和第一条之间的 Markdown (草案说明、## Preamble 及其正文),每种语言一份。其中可以有引用。

一条是一个目录 articles/<NN>-<id>/:条的编号 (两位数字,从 01 起)、一个连字符和条的 ID。目录里的 article.toml 存放 id (等于去掉编号的目录名)、[title]、可选的 [intro] (标题与第一款之间的那段文字),以及只在整条废止时才有的 repealed = "YYYY-MM"。

每一款是所在条目录里的一个文件 <NN>[a-z]-<id>.toml:款的编号 (两位数字,从 01 起,可以带一个小写字母)、一个连字符、款的 ID 和 .toml。款属于存放它的那个目录所代表的条,没有专门的字段记录这一点。文件里存放 id (等于去掉编号和 .toml 的文件名)、status (draft、active 或 repealed)、恰好在状态为 repealed 时才有的 repealed = "YYYY-MM"、可选的 audience = "maintainers" (唯一可取的值,用于讲宪法本身怎样制定、编排和修改的条文),以及 [content],即这一款每种语言的正文:第一行是款号之后的那句话,后面的行、嵌套列表和空行原样跟在后面,构建把它们缩进到列表项之下。

列了项的款,每一项在款的文件里有一张 [[items]] 表:id、number (1、2、2a,在款内编号)、status、repealed 和 audience (与款相同),以及 [items.content],即这一项每种语言的正文。这时款的 [content] 只放引导语;构建把各项按编号顺序渲染在它下面。

id = "must-ask"
status = "draft"

[content]
en = '''
**Must go through a principal** whose authority covers the item ({@explicit-yes}).
'''
zh = '''
**必须经过委托人**,即由权限覆盖该事项的委托人同意 ({@explicit-yes})。
'''

[[items]]
id = "capital"
number = "1"
status = "draft"

[items.content]
en = '''
Capital: allocating, spending, ...
'''
zh = '''
资本:资金和其他有价资源的配置……
'''

条、款、项的顺序只由编号决定,没有另外的列表。index.toml 是 draft 时,每一款、每一项和每条规定都是 draft,没有任何内容被废止;一旦它变成 active,每一款和每一项就是 active 或 repealed。

编号

编号不是根据位置推算的。条的编号是它目录名的前缀,款的编号是它文件名的前缀,只写在那里,别处不写;项的编号是它的 number 字段。款或项的编号是一个整数,可以带一个小写字母后缀 (2、2a),后缀表示后来插在 2 和 3 之间的那一个;条只会追加在末尾,不带后缀。只有在宪法的文本第一次获批准之后,插入的条文才带后缀 (<NN>a-<id>.toml);宪法还是草案时,新条文按顺序取下一个编号,其后的条文依次重新编号。名字前缀就是把这个编号写成两位数字 (02、02a),这样文件按阅读顺序排列。排序先按整数,再按后缀:2 < 2a < 2b < 3。在同一个范围内 (全部条;一条的各款;一款的各项),编号唯一;草案的编号不必连续。

自宪法的文本第一次获批准起,同一版内的编号遵守 stable-numbers;检查 --check --base <git-ref> 对照同一版的一个基准提交来强制这一点 (见检查程序,第 7 项检查):把目录或文件改名为新的编号,或者把一款移到另一条的目录里,都是错误。废止的条文渲染为一行说明,代替它的正文 (见下表)。宪法还是草案时,或者开始新的一版时,编号可以改变,目录和文件随之改名,检查只说明它没有做比对。

渲染示例:must-ask 是第四条的第一款,capital 是这一款的第三项,authority 是这一条的 ID;表中把 <a id="must-ask"></a> 写作 ⟨must-ask⟩:

内容 en zh
标题 # Agent Constitution (2026-10 Edition),即 edition # Agent 宪法 (2026-10 版)
条的标题 ## ⟨authority⟩Article IV. <Title> ## ⟨authority⟩第四条 <标题>
款 - ⟨must-ask⟩**§1** <content> - ⟨must-ask⟩**第一款** <content>
项 - ⟨must-ask.capital⟩(**3**) <content> - ⟨must-ask.capital⟩(**三**) <content>
引用条 [Art. IV][authority] [第四条][authority]
引用款 [Art. IV §1][must-ask] [第四条第一款][must-ask]
引用项 [Art. IV §1(3)][must-ask.capital] [第四条第一款第三项][must-ask.capital]
后缀 §1a、(3a)、Art. IV §1(3a) 第一款之一、(三之一)、第四条第一款第三项之一 (a 是 之一,b 是 之二)
废止的款 - ⟨…⟩**§3** (repealed November 2026) - ⟨…⟩**第三款** (2026 年 11 月废止)
废止的项 - ⟨…⟩(**3**) (repealed November 2026) - ⟨…⟩(**三**) (2026 年 11 月废止)
废止的条 ## ⟨…⟩Article IV (repealed November 2026),下面没有内容 ## ⟨…⟩第四条 (2026 年 11 月废止)
相邻项的引用 Art. IV §1(2) or (4)、Art. IV §1(1) to (7)、Art. IV §1(1), (2) and (4) 第四条第一款第二项或第四项、第四条第一款第一项至第七项、第四条第一款第一项、第二项和第四项
相邻款的引用 Art. IV §1 and §2、Art. IV §1 to §3、Art. IV §1, §2 and §4 第四条第一款和第二款、第四条第一款至第三款、第四条第一款、第二款和第四款

列表标记补足到四个字符宽,一款或一项后面的行 (包括嵌套列表和段落) 都缩进到它正文所在的列:款缩进四个空格,项缩进八个。正文里有空行的款或项,后面跟一个空行。Python-Markdown 只把缩进四个空格的内容当作嵌套,还会把列表行并进紧挨在它上面的段落;按这种排法,只要源文字自己的嵌套块缩进四个空格、段落之后的列表行前面有空行,输出在 Python-Markdown 和 CommonMark (GitHub) 里就渲染得一样。违反其中任何一条的源文字,在 Python-Markdown 里仍会渲染错;宪法目前没有这样的文字。

当一个项的引用前面恰好只有一个连接词,再往前是同一款中另一项的引用时,它渲染成简短形式,只写项的编号 ((4)、(2a);第四项、第二项之一)。款的引用同理:前面是一个连接词,再往前是同一条中另一款的引用时,渲染成只写款的编号 (§2、§1a;第二款、第一款之一)。英文的连接词是 or、and、, 和 to,中文是 或、和、、 和 至;范围在源文件里写成首尾两个引用之间加 to 或 至。别的款中的项、别的条中的款、紧跟在上一级或下一级引用之后的引用 (条和它的款,款和它的项),以及前面有其他任何文字的引用,都保留完整路径。源文件里始终写完整路径。

每一条、每一款、每一项都以一个用 ID 而不是编号命名的锚点开头:<a id="<article-id>">、<a id="<section-id>"> 和 <a id="<section-id>.<item-id>"> (ID)。锚点在每种语言里都相同,重新编号后也不变;条和款的 ID 在整部宪法内唯一,所以不会冲突。引用是指向其条文锚点的链接,简短形式也一样:[Art. IV §1][must-ask] and [§2][…],每个编号各自是一个链接。这些链接是引用式链接,每个被引用的条文在文件末尾有一行定义 [<ref>]: #<ref>,按第一次引用的顺序排列:因为 limae 会把内联链接 […](#…) 的 ) 后面紧跟中文字符的情况,当作一个需要空格的括号 (limae 0.13.3,2026-10 查阅)。款的编号加粗;项的编号在括号内加粗,因为 limae 要求在 ** 和括号之间加空格。

每份输出都以一段纯文本开头,用它自己的语言写:这是生成文件,不要编辑,改源文件;然后是 revision,status 为 draft 时后面跟 (draft) ((草案)),以及语言;在完整版里,如果有部分带星号 (标给维护者的条文,或者序言的标题),还要说明星号的意思:带星号的部分是写给人看的背景,讲宪法从哪里来、怎样组织、怎样修改,agent 版不收录这些部分。输出为 UTF-8 编码,用 LF 换行,末尾有换行符,不带时间戳;同样的源文件得到逐字节相同的输出。

agent 版

agent 通过编译出的指令读宪法,那里每个 token 都很宝贵;序言,以及讲宪法本身怎样制定和修改的条文,对维护宪法的人和起草修正案的 agent 才有用,而起草修正案的 agent 读的是完整版。所以构建为每种语言再写一个文件 constitution.<lang>.agent.md,它与完整版的区别如下:

  • 文件头一行说明这是 agent 版,不含写给人类读者的那些条文的正文。
  • 不收录 [front] (草案说明和序言),所以在完整版里,其中的每个标题 (## Preamble) 后面都带星号。代替它的位置是构建脚本自己的一段说明,每种语言一句,写在 LANGUAGES 里:说明这是 agent 版;index.toml 为 draft 时,说明宪法是草案,可以试行但尚未定稿,变成 active 之后,说明每个 agent 都必须遵守它;说明序言以及写给人类读者、讲宪法怎样组织和修改的条文正文都没有收录,原处只留一个指向完整版的提示;还说明 agent 在修改宪法或构建它的工具之前,要先读完整版,并写出完整版的路径。这段说明不是宪法的正文 (见文件结构)。
  • 带 audience = "maintainers" 的款或项保留编号,用一句说明代替正文:- **§2** (see the full text)、- **第二款** (见完整版);已废止的照常显示废止说明。在完整版里,同一条文保留正文,编号后面带星号 **§2**<sup class="omitted">*</sup>,由文件头一行解释。
  • 没有锚点,也没有链接定义:引用就是它的标签,以纯文本显示 (Art. VIII §6、第八条第六款),在完整版里用简短形式的地方,这里也用简短形式。