Canopy in June 2026 — Highlights

A two-minute summary of a month of work. For the day-by-day version with PR links, see the full June devlog (or the Japanese original).

Canopy is a structure editor written in MoonBit: it treats source code as structure (IR) rather than strings, with text kept as the source of truth. Concurrent editing is built on a CRDT implementing the eg-walker paper. Around it sit a few sibling projects: Loom (incremental parsing), incr (incremental computation), and js_engine (a JS interpreter validated against test262).

1. Structural edits can no longer silently change meaning

Lambda editing reached a milestone: rename, move, duplicate, and extract-to-let now work on bindings inside blocks, not just at the top level — and every edit is validated by re-parsing the resulting text and checking it produces the intended AST. Getting there required scope-graph-based shadowing checks: moving a binding past a lambda parameter can silently redirect references, and ordering checks alone don’t catch it. An alpha-safe beta reduction pilot (computing with binder identity instead of names) landed as well.

2. Edits keep their identity

Wrapping Var(x) in a lambda used to destroy the node’s identity — and with it, your selection and fold state. A new hint channel (IdentityTransform + hinted reconcile) lets edit operations declare their intent (“this is a wrap,” “this unwrap keeps this child”) so NodeIds survive structural edits. Operations that can’t produce a safe hint conservatively opt out. This is one of the core problems any projectional editor has to solve.

3. Markdown became the second structurally-editable language

Headings and list items are now tracked with stable identities that survive broken parses and temporary disappearance (a retention/retired lifecycle, gated on parse validity), and same-list item moves work with unsafe moves properly blocked. The approach — a Structure-Directed Edit Grammar (SDEG) with identity side tables — is what will generalize to further languages.

4. External analysis tools, without corrupting the CRDT

A new analysis query layer ingests results from tools like ast-grep as disposable facts tied to a text snapshot — converted to UTF-16 ranges, shown as editor decorations, and thrown away when stale. The text CRDT remains the only durable state. Phase 1 (snapshot model, offset conversion, decorations) is implemented and on main.

5. js_engine’s spec-conformance push

The MoonBit JS interpreter shipped v0.3.0 and went through a systematic test262 campaign: JSON.parse at 100% (142/142) with Proxy-aware revivers, the lexer made UTF-16-accurate for astral characters, a rewritten regex/division disambiguator, five Promise spec fixes, tombstone-based Set iteration, and a timer queue rewrite (2.15× faster).

6. The build grew up

Every Canopy-owned manifest migrated from moon.mod.json to moon.mod (TOML), with 13 submodules becoming workspace members — killing a long-standing dependency-resolution workaround. Benchmark regression checks moved close to being a PR gate, with an explicit “skipped is not green” rule.


The pace: Canopy’s PR numbers went from #445 to #783 over the month, with parallel work across five sibling repositories, developed in close collaboration with AI agents (Claude Code and Codex) under human review.