Show HN: Jacquard —— 一种专为AI编写、人工审核代码设计的编程语言
摘要
Jacquard是一种专为AI编写、人工审核代码而设计的编程语言,内置效果跟踪、概率模拟和规范标识,帮助人类信任AI生成的程序。
查看缓存全文
缓存时间: 2026/07/13 22:56
jbwinters/jacquard-lang
来源:https://github.com/jbwinters/jacquard-lang
Jacquard
持续集成(https://github.com/jbwinters/jacquard-lang/actions/workflows/ci.yml) 发布(https://github.com/jbwinters/jacquard-lang/releases)
Jacquard 是 FriendMachine 的一个研究项目,用于运行、审查、模拟和信任由模型编写并由人类审查的程序。请从面向人类的 Jacquard 介绍(https://research.friendmachine.co/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 还揭示了它可能执行的效应、有限的离散不确定性以及规范的程序身份。工具可以检查所有这些,因为它们存在于语言中,而不只是存在于注释、日志或你对代码库的记忆中。
以下是一些这里能做、而大多数语言无法提供的事情:
- 阅读一行就能看到函数可能执行的效应。像
(text) ->{net} text这样的签名表示该函数可能执行net效应。Jacquard 运行时拒绝未处理的世界效应,除非使用--allow显式授权,包括动态代码执行的效应。这是研究运行时中的语言级强制,不能替代操作系统沙箱。 - 对同一程序运行多个世界。同一份代码可以针对真实网络、脚本模拟的假数据、上周流量的录制回放,或者关于服务器通常行为方式的概率模型来运行。处理器(handler)是回答程序对外部世界的请求的组件;你只需替换处理器,而代码本身从不改变。这可以取代许多在效应边界上的传统模拟(mocking),并使“如果 API 宕机我的代理会怎么做”成为一次普通的测试。
- 为有限的离散模型枚举精确概率。程序可以对带权重的选择进行采样并记录证据,枚举会列出每个可达结果及其精确概率。下面的修复演示将失败的测试视为证据,并计算哪些补丁仍然可能及其可能性大小。
- 重命名和重新格式化而不改变规范身份。Jacquard 对规范解析后的结构进行哈希,而不是对源码字节进行哈希。注释、格式、来源以及普通局部或项的重命名都会被忽略;纯测试仅在规范代码或依赖内容发生变化时重新运行。这是结构身份,而非任意程序行为等价的证明。
这一切背后的赌注是:当大多数代码由机器编写时,审查代码的人类需要语言本身来回答“这段代码能接触到什么,我们有多确定”,而不必逐行阅读。
面向智能体
首先阅读 docs/SKILL.md。它将内核、CLI、前导、Warp 测试以及已知陷阱压缩成一个文件,并从 docs/SKILL.md 作为项目技能加载。操作规则见 AGENTS.md。以下内容可以节省你的时间:
- 行为由 pin 固定:
test/cli/下的 cram 转录、语料库的金标准、演示脚本以及docs/release/0.1/CLAIMS.md。如果 pin 失败,将其视为关于你的变更的信息,永远不要为了通过 diff 而削弱 pin。 - 内核有 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/泄漏/fuzz 通道以及一个全新克隆的证据工作流固定。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 变异为候选补丁,将失败的测试视为观察,然后读取更新后的概率。运行候选代码是一种权限,因此纯步骤仍然运行(它计数了八个候选补丁),然后演示拒绝继续,直到你授予权限:
$ 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)。添加一个回归测试即可剔除冒名顶替者,幸存修复打印为一行规范 diff:- 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;其他平台目前需要开发环境。
发布归档文件附加在 jacquard-core-* GitHub 版本中。每个归档包含 bin/jacquard、bin/jac、libexec/jacquard/jacquard、share/jacquard/prelude、share/jacquard/demos、原生 C 运行时以及许可、声明、例外和商标文档。
快速开发指南
以下命令假设全新克隆且已安装 asdf 用于安装 opam。如果你已经有 opam 2.5.x,从本地 switch 步骤开始。如果 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
switch 步骤会从源码编译 OCaml 5.1.1,因此首次设置预计需要大约十分钟。
最后的 git diff --exit-code 是开发契约的一部分:格式化必须保持工作目录干净,除非你有意提交格式化差异。
设置后的预期版本:
opam2.5.1(来自.tool-versions)- OCaml 5.1.1(来自仓库本地的
_opam/switch) dune、ocamlformat、alcotest、qcheck、digestif、menhir、cmdliner、odoc、utop和ocaml-lsp-server(来自jacquard.opam)
在现有检出目录中的新 shell 里运行:
eval "$(opam env)"
_opam/ 被有意忽略。它是本地构建产物,而非源码。
运行 Jacquard
在开发期间,通过 Dune 使用构建的二进制文件:
opam exec -- dune exec jac -- --help
opam exec -- dune exec jac -- --version
许多直接 CLI 命令需要前导。从仓库根目录:
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设置程序栈大小(默认 1024):深度非尾递归在这个后端中就是真实的 C 递归。- 编译后的单元在
.jacquard-native/下缓存,以内容为键,因此未变动的程序无需重新编译即可重新链接。 - 测量性能存在于
docs/benchmarks.md中——九个场景,包含解释器、原生(两种工具链)、Python 和手写 C 列——声明边界在docs/native-compilation.md中(使用scripts/native-bench.sh可重现)。
演示
在 dune build @all 之后,从仓库根目录开始查看这些演示。同样的脚本也可以在已安装的 bundle 中运行,无需 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/:一个结账策略在模拟网络和时钟定律下的运行、精确事故预测以及覆盖所有 27 个世界的 Warp 证明。case-studies/release-risk/:一个发布策略在具体世界和概率世界下的运行。
相似文章
@EBorgnia:今天,我们推出了 Jacq。这是一个编码代理,与我们一直在@relace_ai 训练的小模型一起构建,用于……
Jacq 是一个基于云的编码代理,与 Slack、Linear、GitHub、电子邮件和其他工具集成,使用 Relace AI 训练的小模型从连接的设备中提取上下文,并维护持久线程以记录工作历史。
Show HN: Juggler – 一个开源GUI代码智能体,由JUCE的创建者开发
Juggler是一个开源GUI代码智能体,提供了一个可视化工作台,用于与LLM交互以编辑代码,具有可检查的工具调用、分支线程和可编辑上下文。它可以在本地或远程运行,并支持多种模型。
Jam 编程语言
Raphael Amorim 宣布了 Jam,一种旨在结合 Rust 的安全性和 Zig 的简洁性的新编程语言,解决了在 AI 生成代码时代现有系统语言的复杂性和验证开销。
Show HN: Mach – 一款寻求贡献的编译型系统语言
Mach 是一种静态类型、编译型的系统语言,旨在实现简洁性、明确性和可维护性。它是开源的,并在 GitHub 上寻求贡献。
Anthropic的Code with Claude展示了编程的未来——无论你喜欢与否
Anthropic在伦敦举办的Code with Claude活动展示了像Claude Code这样的AI编码工具如何自动化软件开发,开发者越来越将代码编写和调试交给AI。'dreaming'等新功能允许Claude代理共享笔记并从过去的错误中学习。