AI can produce code faster than a person can review it. That moves the bottleneck. Getting a plausible function onto the screen is cheap. Establishing what it can touch, how it behaves when the world goes wrong, and whether an edit changed anything meaningful still takes careful review.

Jacquard is a research programming language built around that job. A function's type shows what it may ask the outside world to do. The same program can run against real services, recorded events, or simulated failures. Code identity ignores formatting, comments, and ordinary renames.

Probability and exhaustive branching use the same effect-handler machinery. They do not require a separate testing or modeling language.

What's borrowed, what's combined

Jacquard borrows from algebraic-effect languages such as Koka, Eff, Effekt, and Frank; from capability systems; from probabilistic systems such as Gen and Pyro; and from content-addressed systems such as Unison and Nix. None of those ideas began here. The experiment is to combine them around one problem: reviewing and approving code produced faster than a person could have written it.

Working with models on a new language

I used coding models while developing the compiler, runtime, standard library, documentation, and test suite. There was no pre-existing Jacquard corpus for the models to imitate. With a self-contained SKILL.md, repository context, executable tests, a small kernel, and a tight checker loop, they could still contribute and write public-syntax programs. Their recurring mistakes are familiar-language guesses: imports, field accessors, infix arithmetic, string interpolation, and handler behavior Jacquard does not provide. The checker catches effect-row mismatches and ill-typed resumption calls. Properties, replay, and exhaustive tests catch programs that type-check but make the wrong decision.

Effects appear in the type

Ordinary code review often requires reconstructing possible effects from implementation and context. Jacquard puts those effects in function types. This policy body asks for three telemetry values, and its signature exposes that requirement:

effect Telemetry where {
  inventory-health : () -> Health
  payments-health : () -> Health
  error-spike? : () -> Bool
}

release-assessment : () ->{Telemetry} Assessment
release-assessment() = {
  let inventory = inventory-health()
  let payments = payments-health()
  let spike = error-spike?()
  Assessment(inventory, payments, spike,
    decide(inventory, payments, spike))
}

{Telemetry} shows the effects this function may perform at this layer. It may ask for telemetry, but it cannot directly use the network or filesystem. Higher-order functions carry effects from the functions they receive, and handlers remove only the effects they handle.

Once handlers are chosen, any world effects left at the root are the program's authority requirements. Network and filesystem effects require explicit --allow grants, for example jac run policy.jac --allow net --allow fs. If execution reaches an ungranted effect, it stops with a diagnostic. The checker can compare inferred requirements with an expected manifest without running the program.

The threat model is accidental or unnoticed authority growth in generated code. A whole-network grant does not stop a malicious program from using that network access, and 0.1 has no host allowlists or path-scoped grants. There is no user-facing general C FFI in 0.1. Language-level checks still belong inside an operating-system sandbox when the code is untrusted.

One policy, three passes

The installed release-risk demo shows the central workflow. It prints the policy's inferred requirement, runs the policy against one concrete telemetry snapshot, calculates the probability of each release decision conditioned on a failed checkout, and asks Warp to verify the safety rule across all 18 modeled telemetry worlds.

$ sh ~/.local/share/jacquard/demos/case-studies/release-risk/run.sh
== inferred authority ==
release-assessment : () ->{Telemetry} Assessment

== the same policy under a concrete snapshot handler ==
assessment(healthy, degraded, false, canary(5))

== the policy under a probabilistic telemetry handler ==
0.305077  canary(5)
0.295394  hold("inventory-down")
0.184621  canary(10)
0.155903  hold("payments-down")
0.059005  ship

== Warp: exhaustive proof over all 18 telemetry worlds ==
PASS a down service is never approved to ship
  (verified exhaustively (18 cases))
3 passed, 0 failed, 0 skipped, 0 refused

The transcript is shortened here, but its values and test result are pinned in the release-risk demo and command-line test suite. Every major release claim has a corresponding test, negative case, and stated caveat in the 0.1 claim matrix.

One program, several worlds

An effect describes a request. A handler decides how that request is answered. The production handler can call a real service. Another handler can return a script, replay recorded interactions, or model weighted outcomes. The requesting program stays the same. In the demo, one handler supplies today's telemetry snapshot and another supplies a probability model after a failed checkout. This lets a reviewer test policy under outage, stale-data, and hostile-input worlds before connecting it to production resources. A production run still needs explicit permission for any world effects left after its handlers are installed.

Probability uses the same machinery

Jacquard represents finite uncertainty through a regular Dist effect. Programs choose among weighted options and record evidence. A handler chooses how to calculate the result. Exact enumeration visits every reachable outcome for a finite model within the configured budget. Seeded likelihood weighting samples when full enumeration is too expensive.

Under the hood, a multi-shot handler resumes the rest of a computation once for each branch and combines the results. The current implementation has no continuous distributions, gradients, or general-purpose probabilistic optimizer.

Warp tests the program in place

Warp is Jacquard's test framework. Pure cases and seeded properties are deterministic and cacheable. World tests are separate and require explicit grants. Strict replay fails when a program's requests drift from recorded interactions. Tests can swap handlers instead of building a mocking layer, and fault handlers explore failures at effect boundaries.

An exhaustive property can run every supported fault path within a budget. Warp's cache follows resolved dependencies: formatting and comments do not rerun a pure test, while a structural dependency change invalidates its tests.

Code identity survives harmless edits

Jacquard definitions are addressed by a SHA-256 hash of canonical, resolved structure. Formatting, comments, provenance, and ordinary local or term renames are removed before hashing. An edit that changes resolved structure changes the hash. This supports structure-aware diffs and exact build caches. The claim is narrow: equal hashes mean equal canonical structure under the current serialization rules, not proof that arbitrary programs behave the same.

A working native compiler

Public programs use the compact .jac syntax. They lower to a 27-form kernel shared by the checker and interpreter. The implementation includes an OCaml type-and-effect checker, a CPS interpreter, a Jacquard-written standard library, the command-line tool, Warp, and a native ahead-of-time backend.

The native backend emits C, specializes reachable definitions, and caches compiled units by content hash. Native and interpreted runs are checked against each other under clang and gcc. Public .jac programs and kernel .jqd programs share the same semantics, but the build command currently takes the serialized kernel carrier directly. Wiring surface parsing into that command remains open work. The benchmark programs below use the kernel carrier and pass the interpreter/native differential tests.

Performance is not Jacquard's main claim. These measurements establish that the backend runs substantial programs at plausible speed. The table is a subset of a July 6 run on a Ryzen 9 7950X3D: median of five wall-clock runs per cell, with measured engine startup subtracted. The C column is raw, so its process startup remains included.

Program Jac interpreter Jac native (clang 18) Python 3.11 Hand C
fib726 ms4 ms71 ms3 ms
sort67,728 ms96 ms262 ms25 ms
sum13,922 ms54 ms62 ms23 ms
text182 ms10 ms10 ms5 ms
state loop*24,181 ms159 ms76 ms3 ms
code mutation*2,558 ms4 ms9 ms2 ms

Native compilation cuts these interpreter times by roughly 18 to 700 times. On the specific benchmark twins, native Jacquard is faster than Python on fib, node-based merge sort, list sum, and the task-equivalent code-mutation case; the text test has the same measured median as Python. Handled state is slower than Python method calls because it pays for the handler and continuation machinery rather than a direct method dispatch.

* State loop and code mutation are task-equivalent comparisons: C and Python use their native mechanisms rather than Jacquard's handler or code-value representation. The full benchmark record includes gcc, methodology, variation, and the limits of each comparison.

What exists, and what does not

Jacquard Core 0.1 works end to end as a release candidate. Published binaries cover Linux x86-64, macOS Intel, and macOS Apple Silicon. The repository includes executable demos, a claim matrix tied to tests, and a separate limits document.

The current boundary matters:

  • The surface syntax is usable and still evolving.
  • There is no language package manager or public registry yet.
  • The interpreter and native runtime are single-threaded.
  • Root grants cover whole effects rather than paths, hosts, or quotas.
  • Probability is finite and discrete.
  • The checker and runtime have extensive tests, but no formal soundness proof or security audit.

Package management, editor tooling, direct surface-to-native builds, runtime optimization, and ordinary language conveniences remain open work. I expect the syntax to change as people use it.

Jacquard is licensed under the Apache License 2.0. Programs written and compiled with Jacquard can use any license their authors choose.

Try a small program

The release installer does not require OCaml or opam. It downloads a checksum-verified binary, the prelude, demos, and the native runtime:

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

The second command prints 120. For coding agents, start with docs/SKILL.md. It contains the syntax, command reference, testing model, and common mistakes in one file.

To inspect the archive before running anything, download it and its checksum from the release page. For Linux x86-64:

VERSION=jacquard-core-0.1-rc3
TARGET=linux-x86_64  # or macos-arm64 / macos-x86_64
BASE=https://github.com/jbwinters/jacquard-lang/releases/download/$VERSION
curl -fLO "$BASE/jacquard-$TARGET.tar.gz"
curl -fLO "$BASE/jacquard-$TARGET.tar.gz.sha256"
if command -v sha256sum >/dev/null 2>&1; then
  sha256sum -c "jacquard-$TARGET.tar.gz.sha256"
else
  shasum -a 256 -c "jacquard-$TARGET.tar.gz.sha256"
fi
tar -tzf "jacquard-$TARGET.tar.gz"

After verification, unpack the archive and inspect its packaged README before copying bin, libexec, and share into your chosen prefix.

The name comes from the Jacquard loom, whose punched cards helped turn weaving into programmable control. Warp is the test framework. That part was too apt to leave unused.

The useful test now is small and concrete: ask an agent to write one effectful policy, one handler, and one Warp property. Reports about confusing syntax, missing library pieces, weak diagnostics, and places where an agent confidently writes the wrong thing will shape the next release.