Jacquard:为AI编写、人类审查代码而设计的编程语言
Jacquard 是 FriendMachine 旗下的研究项目,专为运行、审核、模拟和信任「模型编写、人工审核」的程序而设计。入门请阅读Jacquard 人性化介绍。
具体而言,它包含以下组件:一门语法简洁的小型编程语言(文件后缀为 .jac)、基于 OCaml 的检查器与 CPS 解释器、可生成 C 代码的原生 AOT 后端(当前可编译核心 .jqd 载体)、命令行工具、用 Jacquard 编写的标准库,以及名为 Warp 的测试框架。0.1 版本已实现端到端功能,但仅为研究原型,并非生产级语言;docs/release/0.1/LIMITS.md 文件明确说明了其能力边界。
无需安装 OCaml 或 opam,直接安装 0.1 版本候选版:
curl -fsSL https://raw.githubusercontent.com/jbwinters/jacquard-lang/jacquard-core-0.1-rc3/scripts/install.sh | sh
~/.local/bin/jac run ~/.local/share/jacquard/demos/basics/m1-fact.jac
预期输出为 120。目前已发布 Linux x86-64、macOS Intel 和 macOS Apple Silicon 版本的二进制文件;从源码编译的方法见下文。
接下来,在具体环境和概率遥测环境下运行同一策略,再执行抽样式与穷尽式 Warp 检查:
sh ~/.local/share/jacquard/demos/case-studies/release-risk/run.sh多数编程语言只会告诉你程序的计算结果,而 Jacquard 还会暴露程序可能产生的副作用、有限离散不确定性,以及程序的标准标识。由于这些信息内置于语言本身,而非仅存在于注释、日志或开发者对代码库的记忆中,工具可直接对其进行检查。
Jacquard 具备多数语言没有的特性:
- 一行代码看清函数副作用。例如签名
(text) ->{net} text表示该函数可能产生net(网络)副作用。Jacquard 运行时会拒绝未处理的全局副作用,除非通过--allow参数明确授权,包括动态代码产生的副作用。这是研究级运行时在语言层面的强制限制,不能替代操作系统沙箱。 - 同一程序适配多环境。代码无需修改,只需切换「处理器」(handler),即可对接真实网络、模拟脚本、上周流量记录,或是服务器行为概率模型。处理器负责响应程序对外部环境的请求,可替代传统测试中大量针对副作用边界的模拟工作,让「API 故障时我的代理程序会如何表现」这类问题成为常规测试场景。
- 为有限离散模型枚举精确概率。程序可进行带权重的抽样并记录证据,枚举功能会列出所有可达结果及其精确概率。下方的修复演示将失败测试视为证据,计算出所有可行补丁及其概率。
- 重命名、格式化不改变标准标识。Jacquard 对标准化解析结构进行哈希运算,而非基于源码字节。注释、格式、来源信息以及普通的局部或术语重命名都会被忽略;只有当标准代码或依赖内容发生变化时,纯测试才会重新运行。这是结构标识,并非证明任意程序行为等价。
这一切背后的核心假设是:当大部分代码由机器生成时,人工审核者无需逐行阅读,只需通过语言本身就能回答「这段代码会影响什么?我们有多大把握?」。
建议先阅读 docs/SKILL.md,它将核心语法、命令行工具、前置库、Warp 测试及已知陷阱浓缩为一份文档,可作为项目技能手册加载。操作规范详见 AGENTS.md。以下技巧能帮你节省时间:
- 行为由证据固定:
test/cli/下的 cram 脚本、语料库基准输出、演示脚本,以及docs/release/0.1/CLAIMS.md均为证据。若证据校验失败,应将其视为修改带来的信息,绝不能为了让代码差异通过而弱化证据。 - 核心语法仅包含 27 种形式(见
docs/ast.md);.jac是这些形式的上层语法,而引导式.jqd格式将永久得到支持。请将已发布的上层语法边界及其后续规划视为发布证据,而非固定语法;不要添加超出范围的功能(AGENTS.md列出了此类功能)。 - 开发准入标准为:
dune build @all && dune runtest && dune fmt执行完成后,git diff --exit-code无任何输出。
面向编程语言开发者的技术细节:
- 统一表示形式:所有语法单元均为
(head, meta, args)三元组,核心语法共 27 种形式。被引用的代码是普通数据。 - 支持深度多续程的代数副作用。处理器可让计算续行零次、一次或多次,这使得穷尽搜索和精确推理可通过标准库实现,无需内置到运行时。
- 显式权限授予。运行时仅为
--allow参数指定的副作用安装外部环境处理器,不存在默认权限。 - 类型与副作用行。每个函数箭头类型都携带其可能产生的副作用集合,因此程序的推导行就是其权限清单。
- 离散概率编程作为库实现:
sample(抽样)和observe(观测)是副作用操作,每种推理算法对应一个处理器。 - 内容寻址定义。标识是标准化解析结构的哈希值,非标识元数据会被移除,因此格式、注释及普通重命名不会影响下游流程。
- 基于上述特性的工具集:格式化工具、结构感知差异对比工具、带内容寻址缓存的 Warp 测试、记录/重放功能,以及可复现的发布证据包。
- 原生 AOT 编译路径:生成 C 代码,按内容哈希对单元进行特化和缓存,并通过 clang 和 gcc 与解释器进行差分测试。
该原型已完成最初的核心规划,后续新增了公共上层语法、环形标准库、Warp 属性与缓存、原生编译、打包二进制文件,以及产品级案例研究。RC1 的语义边界由 554 个 Alcotest/QCheck 测试用例、32 个 cram 脚本、21 个文档示例、原生 sanitizer/内存泄漏/模糊测试流程,以及全新克隆的证据工作流固定。RC2 修复了二进制演示包的问题;RC3 添加了明确的运行时/输出许可例外,并打包了原生运行时。当前后续版本将 Jacquard 重新授权为 Apache License 2.0,并保留了运行时/输出权限的明确说明。这些许可和打包变更未改变 RC1 固定的语言语义。
以下示例展示了一个处理器两次续行同一计算过程。代码已逐字节复制到 test/docs-doctest/fixtures/readme-multishot.jac,由文档测试流程运行:
effect Choice where {
choose : () -> Bool
}
handle {
match choose() {
| True -> 1
| False -> 2
}
} {
| return x -> x
| choose() resume continue -> add(continue(True), continue(False))
}
$ jac run test/docs-doctest/fixtures/readme-multishot.jac
3
处理器分别传入 true 和 false 运行剩余程序,然后汇总两个结果。正是这种多次续行的能力,让精确贝叶斯推理可作为库处理器实现,而非运行时特性。修复演示在此基础上展开:将有 bug 的程序 AST 转换为候选补丁,将失败测试视为观测结果,然后读取更新后的概率。运行候选代码需要权限,因此纯计算步骤会正常执行(统计出 8 个候选补丁),之后演示会暂停,等待你授予剩余权限:
$ jac run demos/tooling/repair.jac
8
error[E0814]: this program requires the `eval` effect, which is not granted (performed via `posterior-over-patches`)
hint: grant it with --allow eval, or handle the effect in the program
$ jac run demos/tooling/repair.jac --allow eval
获得授权后,一次失败测试会筛选出两个可行补丁:预期修复的概率为 0.75,另一个投机取巧通过测试的补丁概率为 0.25。添加一个回归测试即可剔除后者,剩余的修复方案会以一行标准结构差异的形式输出:- sub + add。完整脚本详见 sh demos/tooling/repair.sh。
多数用户无需安装 OCaml 或 opam。执行以下命令安装经过审核的 0.1 RC 版本二进制文件:
curl -fsSL https://raw.githubusercontent.com/jbwinters/jacquard-lang/jacquard-core-0.1-rc3/scripts/install.sh | sh安装程序会自动检测你的操作系统和 CPU,下载匹配的压缩包及 SHA-256 校验和,若校验和不匹配则终止安装,默认安装到 ~/.local 目录。请确保 ~/.local/bin 已加入 PATH,然后运行:
jacquard --version
jac --version
jac 是 jacquard 的简写别名。两个命令都会从安装包中自动设置 JACQUARD_PRELUDE 环境变量,因此常规运行无需手动配置:
jac run ~/.local/share/jacquard/demos/basics/m1-fact.jac叙事演示自带启动器,可自动选择已安装的二进制文件和前置库,无需依赖 Dune:
DEMO_ROOT="$HOME/.local/share/jacquard/demos"
sh "$DEMO_ROOT/case-studies/release-risk/run.sh"
sh "$DEMO_ROOT/worlds/agent-dream.sh"
sh "$DEMO_ROOT/worlds/escrow/run.sh"
请使用这些启动器运行概率模型或多文件入口程序,而非直接执行。启动器会在需要观测时自动选择 infer 模式,并在独立的临时目录中组装相关文件。
如需安装到其他用户自定义路径:
curl -fsSL https://raw.githubusercontent.com/jbwinters/jacquard-lang/jacquard-core-0.1-rc3/scripts/install.sh \
| JACQUARD_INSTALL_PREFIX="$HOME/.jacquard" sh
设置 JACQUARD_INSTALL_VERSION 可安装指定版本的发布标签。支持的二进制目标平台包括 linux-x86_64、macos-x86_64 和 macos-arm64;其他平台目前需从源码编译。
发布压缩包附在 GitHub 的 jacquard-core-* 发布版本中,包含 bin/jacquard、bin/jac、libexec/jacquard/jacquard、share/jacquard/prelude、share/jacquard/demos、原生 C 运行时,以及许可、声明、例外和商标文件。
以下命令假设全新克隆代码库,且已安装 asdf 用于安装 opam。若已安装 opam 2.5.x,可直接从本地环境切换步骤开始;若机器上已初始化 opam,可跳过 opam init。
git clone https://github.com/jbwinters/jacquard-lang.git
cd jacquard-lang
asdf plugin add opam https://github.com/asdf-community/asdf-opam.git
asdf install opam 2.5.1
asdf set opam 2.5.1
asdf reshim opam 2.5.1
opam init -y --no-setup --bare
opam switch create . ocaml-base-compiler.5.1.1 -y
eval "$(opam env)"
opam install --deps-only . --with-test --with-dev-setup --with-doc -y
opam exec -- dune build @all
opam exec -- dune runtest
opam exec -- dune fmt
git diff --exit-code
环境切换步骤会从源码编译 OCaml 5.1.1,首次安装约需 10 分钟。
最后的 git diff --exit-code 是开发约定的一部分:除非有意提交格式变更,否则格式化后工作区必须保持干净。
安装完成后预期版本:
opam2.5.1(来自.tool-versions)- OCaml 5.1.1(来自代码库本地
_opam/环境) dune、ocamlformat、alcotest、qcheck、digestif、menhir、cmdliner、odoc、utop和ocaml-lsp-server(来自jacquard.opam)
在已克隆代码库的新终端中,运行以下命令初始化环境:
eval "$(opam env)"代码库已忽略 _opam/ 目录,它是本地构建产物,不属于源码。
开发过程中,可通过 Dune 调用编译好的二进制文件:
opam exec -- dune exec jac -- --help
opam exec -- dune exec jac -- --version
许多直接的命令行操作需要前置库。在代码库根目录运行:
export JACQUARD_PRELUDE=$PWD/prelude
opam exec -- dune exec jac -- run demos/basics/m1-fact.jac
主要命令如下:
jac run FILE.jac [--allow fs] [--allow net] [--dry-run]
jac check FILE.jac [--print-sigs] [--manifest fs,net,console]
jac hash FILE.jac
jac fmt FILE.jac
jac diff FILE_A.jac FILE_B.jac
jac diff STORE_A STORE_B
jac infer enumerate MODEL.jac
jac infer lw MODEL.jac --seed 42 --samples 100000
jac replay TRACE.jqd PROGRAM.jqd [--fork '1=(response 500 "down")']
jac test TESTS.jac [TESTS.jqd ...] [--exhaustive] [--cache-dir CACHE]
jac build FILE.jqd -o PROG
.jac 是面向用户的上层载体。引导式 .jqd 格式作为内部/调试语法、引用标记和记录用核心格式,仍得到全面支持。run、check、hash、fmt、diff、infer 和 test 命令会根据文件扩展名自动选择上层语法;原生构建、重放程序、前置库及许多内部测试用例则继续使用 .jqd 格式。
普通程序和演示只需 .jac 源码文件。除非一致性测试需要证明两种载体可转换为相同核心语法并生成相同哈希,否则无需手动编写 .jqd 对应文件。语料库和部分演示中保留的成对文件是证据测试用例,并非编写要求。
jacquard build 目前仅支持核心 .jqd 载体,可将程序及其可访问的声明编译为独立二进制文件,其输出(标准输出、标准错误和退出码)与 jacquard run 完全一致,这一特性由 CI 中的差分测试工具(scripts/native-diff.sh)固定。完整的副作用语言均可编译,包括捕获和多续程处理器;自任务 73 起,代码值也可编译,包括引用、拼接和结构化代码操作。仅 eval 操作仍需在解释器层面运行(遵循 E1102 策略:动态加载的代码在权限模型所在环境运行)。
export JACQUARD_PRELUDE=$PWD/prelude
export JACQUARD_RUNTIME=$PWD/runtime
jac build demos/tooling/word-count.jqd -o word-count
echo "some words some" | ./word-count --allow console
环境要求与配置选项:
- 发布版二进制文件会自动识别打包的前置库和 C 运行时。源码克隆版可通过设置上述两个环境变量指定路径。
- 需要 C 工具链:clang(任意新版本)或 gcc。所有工具链均支持尾调用 O(1) 栈空间:clang 和 gcc 15+ 使用 musttail,更低版本使用 trampoline(生成的 C 代码完全相同)。
- 二进制文件支持解析
--allow EFFECT(目前支持 console、clock、fs、dist、infer)、--seed N(用于抽样授权),若使用--infer-cache和--dry-run(解释器工具)会明确报错。 JACQUARD_STACK_MB用于设置程序栈大小(默认 1024MB):该后端中深度非尾递归会直接转换为 C 递归。- 编译单元会缓存到
.jacquard-native/目录,以内容为键,因此未修改的程序可直接重新链接,无需重新编译。 - 性能测试结果见
docs/benchmarks.md——包含 9 个场景,对比了解释器、原生编译(两种工具链)、Python 和手写 C 的性能;相关声明边界见docs/native-compilation.md(可通过scripts/native-bench.sh复现)。
完成 dune build @all 后,可从代码库根目录运行以下脚本。这些脚本在已安装的二进制包中同样可用,无需依赖 opam 或 Dune:
opam exec -- sh demos/case-studies/stormglass/run.sh
opam exec -- sh demos/case-studies/release-risk/run.sh
opam exec -- sh demos/basics/m1.sh
opam exec -- sh demos/inference/m3.sh
opam exec -- sh demos/worlds/agent-dream.sh
opam exec -- sh demos/worlds/preflight.sh
opam exec -- sh demos/tooling/repair.sh
各脚本展示内容:
case-studies/stormglass/:模拟网络和时钟规则下的 checkout 策略、精确事件预测,以及针对全部 27 种环境的 Warp 验证。case-studies/release-risk/:具体环境和概率遥测环境下的发布策略,以及针对全部 18 种环境的 Warp 安全性验证。basics/m1.sh:阶乘计算、多续程选择,以及 gated eval。inference/m3.sh:同一模型分别进行精确枚举和似然加权推理;模型哈希相同,仅推理处理器不同。inference/clarifying-question.sh:代理程序计算向用户提问是否值得(信息价值)。worlds/agent-dream.sh:脚本化和概率化环境处理器下的策略演示。worlds/preflight.sh:候选代理计划在不同环境下的评分;即使模拟通过,实际策略仍需 Net 权限授权。inference/ambiguity-pipeline.sh:保留不确定性的提取流程;用户点击会触发observe操作。tooling/showcase-warp-tests.sh:针对 clarifying-question、dream-mode 和 ambiguity 演示的 Warp 检查。tooling/repair.sh:将程序修复视为贝叶斯推理;bug 报告作为对单编辑补丁的观测结果,最可能的修复方案以一行标准结构差异形式输出。worlds/m4-hostile.sh:看似自动生成的代码尝试获取net权限;签名和权限清单会暴露其权限需求。worlds/escrow/run.sh:产品级生成工作流,包含权限清单、试运行、Warp 测试、故障排查、重放、标准差异对比,以及基于哈希的审批。
演示路径按分类目录规范命名,无扁平化兼容别名。完整目录见 demos/README.md。
所有公开演示的输出均由 cram 测试固定(记录的命令行脚本会在输出偏离时失败),尤其是 test/cli/demos.t、test/cli/hostile-demo.t、test/cli/escrow.t、test/cli/showcase.t、test/cli/repair.t、test/cli/preflight.t,以及针对大型应用的 test/cli/case-studies.t。
候选版发布证据包位于 docs/release/0.1/。
从当前克隆版本复现发布证据:
JACQUARD_RELEASE_REF=HEAD JACQUARD_RELEASE_BASE=738dc8e scripts/release/reproduce-0.1.sh该脚本会安装依赖、构建项目、运行完整测试套件、检查格式、运行公开演示、运行严苛测试、记录 jacquard --version,并将生成的证据写入 .scratch/release/0.1/。
关键发布文档:
docs/release/0.1/EVIDENCE.md:构建内容与测试结果docs/release/0.1/CLAIMS.md:映射到测试用例的语义声明及注意事项docs/release/0.1/REPRO.md:全新克隆环境下的复现步骤docs/release/0.1/FREEZE.md:冻结的版本/哈希/存储/命令行界面docs/release/0.1/GAUNTLET.md:已包含和未包含的对抗性测试docs/release/0.1/LIMITS.md:明确的非目标与注意事项docs/release/0.1/DECISION.md:候选版发布决策备忘录docs/release/0.1/RELEASE-NOTES.md:公开候选版内容与安装命令.github/:CI 配置、发布证据工作流、PR 模板AGENTS.md:面向未来编码代理的操作说明bin/:jacquard命令行入口corpus/:一致性语料库与基准输出demos/:可运行示例与产品级演示docs/:设计文档、教程、CI/CD、Warp、标准库、错误说明、发布证据prelude/:Jacquard 标准库与副作用声明scripts/release/:可复现发布证据的脚本spec/:核心 AST 与标准序列化规范src/:OCaml 实现代码test/:Alcotest/QCheck 测试套件及 cram 命令行脚本jacquard.opam、dune-project:包与构建元数据src/form.ml、src/meta.ml、src/span.ml:统一三元组与元数据实现src/reader.ml、src/printer.ml:引导式.jqd标记与格式化工具src/kernel.ml:验证器与带类型核心 ASTsrc/resolve.ml:名称到内容寻址引用的解析src/canon.ml、src/hash.ml:HASH_V0 标准序列化与哈希实现src/store.ml:对象存储与可变名称索引src/value.ml、src/eval.ml:CPS 求值器与多续程处理器src/types.ml、src/check.ml:类型/副作用推导、行类型、权限清单、穷尽性检查src/prelude.ml:前置库加载、内置功能连接与根权限授予src/infer_dist.ml:精确枚举与似然加权实现src/diff.ml:存储间的标准结构差异对比src/warp.ml:Warp 测试发现、运行、缓存与属性验证
新用户建议按以下顺序阅读:
docs/README.md:文档索引与推荐阅读路径docs/tutorial.md:可运行的用户示例demos/README.md:演示目录与各演示的验证点docs/ci-cd.md:GitHub 检查与发布证据流程docs/release/0.1/EVIDENCE.md:候选版发布证据概述
深入设计参考:
docs/whitepaper.tex:早期设计论文,包含动机、风险与相关研究;其路线图与实现状态部分已过时docs/ast.md:核心 AST 与元数据/哈希约定spec/jacquard-kernel-ast-m0.md:核心语法权威规范spec/serialization.md:标准字节格式docs/stdlib.md:前置库与环形标准库docs/warp-testing.md:Warp 测试模型docs/errors.md:诊断信息目录docs/development-plan.md:原始实现规划
提交 PR 前请执行:
eval "$(opam env)"
opam exec -- dune build @all
opam exec -- dune runtest
opam exec -- dune fmt
git diff --exit-code
添加有效的语料库文件后,需重新生成基准哈希:
opam exec -- dune exec test/gen_goldens.exe若修改了面向发布的演示、声明、CI 或语义,还需运行:
JACQUARD_RELEASE_REF=HEAD JACQUARD_RELEASE_BASE=738dc8e scripts/release/reproduce-0.1.shGitHub Actions 包含三个主要工作流:
CI / Development gate:在 PR、main分支和release/**分支上执行构建、完整测试、格式检查、版本验证及发布文档检查Release Evidence / Reproduce 0.1 evidence:在发布分支、jacquard-core-*标签及手动触发时运行;执行scripts/release/reproduce-0.1.sh并上传脚本输出Release Binaries:在jacquard-core-*标签及手动触发时运行;构建 Linux/macOS 压缩包,包含jacquard、jac、前置库、演示及原生运行时源码
分支保护建议详见 docs/ci-cd.md。
Jacquard 采用 Apache License, Version 2.0 许可。详见LICENSE和NOTICE。
你的程序始终归你所有。仅因使用 Jacquard 编写、检查、解释或编译,Jacquard 不会主张对源码的版权。原生可执行文件包含 Jacquard 运行时代码,因此runtime and generated-output exception明确允许用户程序及编译输出使用作者选择的任何许可,包括专有许可。该例外还免除了仅因编译程序中嵌入运行时代码而产生的 Apache License 声明义务。这是项目许可意图的说明,而非法律建议。
Jacquard 名称与项目标识受TRADEMARKS.md约束。代码许可不授予商标使用权。
Jacquard core 是研究原型,而非生产平台。.jac 上层语法已实现并得到支持,但仍是基于永久 27 种核心形式的演进中 v0 投影。原生 AOT 编译与 C 工具链优化已发布;但 VM/JIT、并发、隔离层强制、连续分布、梯度、类型化暂存、语言包管理、自托管及形式化可靠性证明尚未实现。环境权限授予仍较为粗糙。具体 Core 0.1 语义边界详见 docs/release/0.1/LIMITS.md。
opam: command not found:使用 asdf 和.tool-versions安装opam,或手动安装兼容版本的opam- Dune 无法找到包:在当前终端运行
eval "$(opam env)",然后重新安装依赖:opam install --deps-only . --with-test --with-dev-setup --with-doc -y jacquard无法找到前置库中的名称:设置JACQUARD_PRELUDE=$PWD/prelude,或从代码库根目录通过 Dune 运行- 格式化修改了文件:运行
opam exec -- dune fmt,检查差异,若为有意修改则提交格式变更 - 发布证据默认写入
.scratch/release/0.1/。设置JACQUARD_RELEASE_OUT可指定其他临时输出路径