feat(core): LambdaDelta L0 kernel — reader, value model, evaluator, budget#35
Merged
Merged
Conversation
…udget Phase L0 of ADR-0003: the notebook-agnostic λδ language kernel, built to the confirmed spec v0.1. Headless and fully tested; no UI change. This is the piece everything else (formulas, agents-as-programs, REPL, plugins) will sit on. The kernel / host seam (spec §7), from day one: - `core/src/lambdadelta/` is a self-contained Clojure-flavoured Lisp that KNOWS NOTHING ABOUT NOTES. Reader · value model · evaluator · budget · pure builtins. - `Interp::register_builtin` is the seam: a host (the notebook — the first of possibly many) registers its own builtins as native functions. Nexia-List is simply the first host. This is what makes an SDK/embedding/plugin ecosystem (#33) cheap rather than a later rewrite. A doc-test exercises the seam. What's in: - Reader (reader.rs): total, panic-free. Literals, `()` `[]` `{}` `#{}`, `#uuid`/`#inst` tagged literals (generic `Value::Tagged` — kernel keeps the form, hosts assign meaning), reader sugar `' ` `~` `~@`, `#(… % …)`, `;` comments, commas-as-whitespace. Guards so `nan`/`inf`/`->` stay symbols. - Value model (value.rs): nil/bool/int/float/string/symbol/keyword/list/vector/ set/map/tagged/fn/builtin; truthiness (only nil/false falsy); a reader- compatible printer; a lexical `Scope` with parent chain for closures. - Evaluator (eval.rs): special forms `quote if do let fn def` + quasiquote/ unquote/unquote-splicing exactly per spec §3; closures with lexical capture and `& rest`; keyword-as-function (`(:k m)`) powering multimethod dispatch and `sort-by`; collection literals evaluate their elements. - Sandbox budget (spec §6): per-eval reduction-step ceiling and recursion-depth limit; exhaustion aborts cleanly with an error value — never hangs. - Errors as values (error.rs): unbound/not-callable/arity/type/syntax/ divide-by-zero/budget — structured, never panics. - Pure builtins (builtins.rs, spec §4): arithmetic, comparison, predicates, sequence ops incl. map/filter/reduce/sort/sort-by, sets, strings, maps, and a little reflection (`eval`/`read`/`type`). No notebook I/O — that's a host's job. - WASM: `lambdadeltaEval` browser entrypoint proves the kernel runs in the tab. Deliberate resolutions the spec left open (flagged, not silent): - `=` compares numbers across int/float (`(= 1 1.0)` → true) — JSON attributes make strict variant-equality a footgun. - Collection transformers (map/filter/rest/sort/…) return vectors (the spec's "data" form, §9.4); `conj`/`cons` preserve the natural structure. Deferred to follow-up L0/L1 slices (kept out to keep this reviewable): hygienic `defmacro` + `gensym`/`macroexpand`, multimethods (`defmulti`/`defmethod`), `let`/`fn` destructuring, and the notebook host bindings (`notes`, `set-attr!`, …) that a host registers through the seam. Verification: `cargo test` 66 green (34 kernel unit + 2 property [reader never panics; print→read round-trip] + existing core suite + the seam doc-test); `cargo clippy --all-targets -- -D warnings` clean; `cargo fmt --check` clean; `cargo check --features wasm` clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PAEqVP7Y3bZDhtAaPUTbps
🔍 Hypatia Security ScanFindings: 65 issues detected
View findings[
{
"reason": "Issue in scorecard.yml",
"type": "missing_workflow",
"file": "scorecard.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in boj-build.yml",
"type": "missing_timeout_minutes",
"file": "boj-build.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in casket-pages.yml",
"type": "missing_timeout_minutes",
"file": "casket-pages.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in casket-pages.yml",
"type": "missing_timeout_minutes",
"file": "casket-pages.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in codeql.yml",
"type": "missing_timeout_minutes",
"file": "codeql.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
Hypatia code_safety flagged unwrap/panic sites on the L0 kernel: - reader.rs `read_one` used `forms.pop().unwrap()` on a length-1 vec. Replaced with `forms.remove(0)` (total) so the reader stays strictly panic-free — a real strengthening of the "reader never panics" guarantee, not a suppression. - tests.rs `unwrap()`/`panic!` are the idiomatic assertion mechanism for unit tests (a failed unwrap IS the test failure), not a runtime DoS surface. Added a scoped, documented .hypatia-ignore carve-out for the test file ALONE; the production kernel deliberately stays under the code_safety scanner. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PAEqVP7Y3bZDhtAaPUTbps
🔍 Hypatia Security ScanFindings: 62 issues detected
View findings[
{
"reason": "Issue in scorecard.yml",
"type": "missing_workflow",
"file": "scorecard.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in boj-build.yml",
"type": "missing_timeout_minutes",
"file": "boj-build.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in casket-pages.yml",
"type": "missing_timeout_minutes",
"file": "casket-pages.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in casket-pages.yml",
"type": "missing_timeout_minutes",
"file": "casket-pages.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in codeql.yml",
"type": "missing_timeout_minutes",
"file": "codeql.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
…est module Rewrites the kernel test module to compare whole `Result`s (`assert_eq!(run(x), Ok(y))`) instead of unwrapping. Two wins: - Clears the Hypatia code_safety alerts (unwrap_without_check, panic_macro) on the test file — the gating SARIF check does not consult .hypatia-ignore, so the fix belongs in the code, not the exemption list. Reverts the speculative .hypatia-ignore carve-out; the governance file is back to its prior state. - Assertions now cover the error variant too, and the whole kernel (production AND tests) is free of unwrap/panic. No behaviour change; 32 kernel tests still green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PAEqVP7Y3bZDhtAaPUTbps
|
🔍 Hypatia Security ScanFindings: 62 issues detected
View findings[
{
"reason": "Issue in scorecard.yml",
"type": "missing_workflow",
"file": "scorecard.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in boj-build.yml",
"type": "missing_timeout_minutes",
"file": "boj-build.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in casket-pages.yml",
"type": "missing_timeout_minutes",
"file": "casket-pages.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in casket-pages.yml",
"type": "missing_timeout_minutes",
"file": "casket-pages.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in codeql.yml",
"type": "missing_timeout_minutes",
"file": "codeql.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
hyperpolymath
marked this pull request as ready for review
July 4, 2026 11:57
This was referenced Jul 4, 2026
hyperpolymath
added a commit
that referenced
this pull request
Jul 9, 2026
…lude (#43) ## What this is The **language core, completed** (spec §3) — the second half of "1 then 2": **full macro hygiene**, procedural `defmacro`, **multimethods**, and a **sugar prelude**. Builds on the L0 kernel (#35) and notebook host (#36); the kernel/host seam is untouched, so the notebook host inherits all of this for free. You chose **B — full set-of-scopes hygiene now, in one pass** — and that's what this is: not the weaker Clojure auto-gensym model. ## Full hygiene (and it's genuinely full) Kohlbecker-style **marks**, encoded in symbol names. Each macro expansion gets a fresh mark; quasiquote tags the symbols a *template introduces* with it. Both hygiene properties are implemented **and tested**: | Property | Test | Result | |---|---|---| | Introduced bindings never capture | `(defmacro m [e] \`(let [x 2] ~e)) (let [x 1] (m x))` | **1**, not 2 | | Free identifiers are referentially transparent | `(defmacro inc [n] \`(+ ~n 1)) (let [+ -] (inc 5))` | **6**, not 4 | So the prelude's `and`/`or`/`if-let` use plain `v`/`tmp` with **no `foo#`** — "macro-introduced bindings never capture… *without the author asking*" (spec §3), delivered literally. Mechanics: marked free identifiers fall back to the definition (global) env; special forms **and** macros dispatch on the *base* name (so a marked `let`/`if`/user-macro in a template still works); `Display` strips marks so output stays readable. ## What's in this PR - **`defmacro`** — procedural transformer over *unevaluated* forms; `gensym`, `macroexpand`, `macroexpand-1`. - **Multimethods** (spec §3, open dispatch — not class-OO): `defmulti name dispatch-fn` + `defmethod name dispatch-val [args] …` with `:default`. Dispatch on *any* function of the args — e.g. a note's `:type`: ```clojure (defmulti describe :type) (defmethod describe "task" [n] (str "task:" (:title n))) (defmethod describe :default [n] "other") ``` - **Prelude** (`prelude.rs`) — hygienic sugar written in λδ itself, loaded at `Interp::new()`: `when unless cond and or -> ->> if-let when-let`. ## Files `value.rs` (mark primitives + `MultiMethod` + mark-stripping display) · `mod.rs` (macro/multimethod registries, mark counters, prelude load) · `eval.rs` (hygiene-aware symbol resolution, base-name dispatch, `expand_macro`, `defmacro`/`defmulti`/`defmethod`, quasiquote marking) · `builtins.rs` (`gensym`/`macroexpand`) · `prelude.rs` (new) · `tests.rs` (11 new tests). ## Deliberately deferred `let`/`fn` destructuring; an explicit unhygienic escape hatch (if ever justified); `case`/`match` (pattern matching). Each layers on without touching the seam. ## Verification - `cargo test` — **81 lib tests green** (11 new: user macros, both hygiene properties, multimethods, all prelude sugar, `gensym`, `macroexpand`) + host + golden + invariants + doc-tests. - `cargo clippy --all-targets -- -D warnings` — clean (default **and** `--features wasm`). - `cargo fmt --check` — clean. Production kernel stays **panic-free** (Hypatia-clean). > **Note:** estate governance `workflow_audit` findings are pre-existing estate policy, out of scope; `rust-ci` is the gate here. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01PAEqVP7Y3bZDhtAaPUTbps --- _Generated by [Claude Code](https://claude.ai/code/session_01PAEqVP7Y3bZDhtAaPUTbps)_ Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath
added a commit
that referenced
this pull request
Jul 16, 2026
Verified against the code rather than TOPOLOGY.md, which is stale: claim TOPOLOGY/wiki reality λδ substrate "planned" built (#35, #36, #43 merged) core size ~623 LOC, 12 tests 5,344 LOC, 90 tests green λδ is the largest subsystem in the core (~4,050 LOC, ~76%): reader, value model, evaluator + Budget, hygienic macros, multimethods, prelude, and the notebook host seam. Calling it "planned" materially misrepresents the project to every audience the wiki serves. - Home.md: substrate row planned -> built; status paragraph now cites measured figures and flags that TOPOLOGY.md predates the three LambdaDelta merges. - Developer.md: add the λδ substrate as a first-class stack layer; Track A marked substantially landed, with the outstanding work named (.ld packages, surfacing L2+ through the disclosure ladder). Toolchain verified end-to-end while checking this: `just build-wasm` (with wasm-bindgen-cli 0.2.126, matching Cargo.lock), `just build`, and `just test` all green — 90 Rust + 10 UI tests, including "TEA update delegates to the wasm core". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hyperpolymath
added a commit
that referenced
this pull request
Jul 17, 2026
…fix the Justfile (#46) ## Why `TOPOLOGY.md` predated the three LambdaDelta merges (#35, #36, #43) and never mentioned λδ. Because it is *the* status source, every downstream doc inherited its stale figures — including the wiki landed in #45. This re-derives the countable facts from the tree and corrects the cascade, then fixes the Justfile gaps found along the way. ## TOPOLOGY was understating the project on six axes | Claim | Reality | |---|---| | λδ absent entirely | **Built, not planned** — reader, value model, evaluator + Budget sandbox, hygienic macros, multimethods, prelude, host seam. ~3,400 LOC excl. tests, **~64% of the core**, its largest subsystem. Now its own dashboard row | | "12 passing unit tests" | **90** (81 unit + 3 exchange + 2 golden + 2 property + 2 doc) | | WASM bridge "40%, in progress" | **Wired and exercised** — `Main.res` loads the wasm at boot, `WasmStore` binds 21 of 31 exports, ui-ci runs a TEA↔WASM contract test against the real bundle | | CI "10%, landing in a parallel workstream" | `rust-ci.yml` + `ui-ci.yml` **load-bearing since #22**, SHA-pinned, green on main | | Web/PWA "no service worker yet (planned)" | Service worker + webmanifest + icon **ship and are registered** (`Main.res:88`, #27) | | UI "no drag-and-drop; GraphView placeholder" | Note drag **implemented** (`View.res:397`); GraphView renders a circular layout | **Overall ~35% → ~65%.** The critical path has **moved off the WASM bridge onto the UI surface**: 10 exports are unbound in ReScript, including both λδ entry points (`lambdadeltaEval`, `evalLambdadelta`) — the substrate is reachable from JS but nothing calls it. Also corrects **a mixed-basis error I introduced in #45**: λδ was reported as "~76% of the core" by dividing 4,049 LOC (*with* tests) by 5,344 (*without*). Like-for-like it is 3,407/5,344 = **~64%**. ## Justfile - **`just test` could not work on a clean checkout** — the UI tests import generated `*.res.js` and the wasm bindings, so type-check failed with 4 `TS2307` errors. Now `test → build → build-wasm`. Warm no-op costs ~0.45s, so it is not a tax on the inner loop; added `test-rust` for the Rust-only loop. - **`just check` was weaker than CI** (no `--all-targets`, no `--features wasm`, ran from `core/`) — it could pass locally while CI failed. Now mirrors `rust-ci.yml` exactly. - **`just doctor` ignored the wasm toolchain** — the one thing that actually blocks the browser build. Now checks the wasm32 target and compares the wasm-bindgen CLI against `Cargo.lock`, printing the exact fix command on drift. - **`crg-grade` and `crg-badge` were dead on arrival** — Make-style `$$(...)` under just/sh expanded `$$` to the shell PID, so `(` was a syntax error. They failed 100% of the time. Rewritten as bash shebang recipes. ## Verification - `just check` — pass (now compiles the `wasm` feature, which the old one never did) - `just test` from a **fully cleaned tree** (no `web/wasm`, no `*.res.js`) — rebuilds and passes **90 Rust + 10 UI** - `just doctor`, `crg-grade` (→ `D`), `crg-badge` — all run; doctor's FAIL path verified by hiding wasm-bindgen from `PATH` - `asciidoctor` renders README/ROADMAP/QUICKSTART-DEV clean; `just wiki-sync dry` still previews correctly ## Deliberately not done — needs your call - **`READINESS.md` grade D is probably stale.** All three *Path to C* criteria now appear met (product CI on every PR ✅, UI tests in CI ✅, WASM bridge built + smoke-tested ✅). The grade is assigned by audit, so I corrected the facts and flagged a re-audit rather than self-promoting. `just crg-badge` publishes that letter, so the badge is currently understating the project. - **`must-spdx-headers` is a broken gate** (pre-existing, untouched here). It runs `find . | head -20`, so it checks an arbitrary, readdir-order-dependent fifth of the tree *and* walks vendored `node_modules/`. It currently fails on `@rescript/react`'s own `.res` files — **every tracked source file does have SPDX**. Worse, `contractile.just` has drifted from its source: `contractiles/must/Mustfile.a2ml` contains no `spdx-headers` rule at all, and its `no-hardcoded-paths` rule (severity: **critical**) is missing from the generated file. The `contractile` tool isn't installed to regenerate, and this is your standards ecosystem — so I left it alone. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



What this is
Phase L0 of ADR-0003 — the first implementation of the λδ substrate, built to the just-merged spec v0.1 (#34). A small, homoiconic, Clojure-flavoured Lisp living in the Rust core.
It is headless and carries no UI change — the ADR calls this "the ideal first PR because it carries no UI risk." Nexia-List stays a Tinderbox-like tool you can use for life without ever seeing a parenthesis; this is the engine power users will later reach through opt-in doors (fx fields, a REPL, computational notes).
The kernel / host seam (spec §7) — from day one
core/src/lambdadelta/is a self-contained language that knows nothing about notes: reader · value model · evaluator · budget · pure builtins.Interp::register_builtinis the seam. A host (the notebook — the first of possibly many) registers its own builtins as native functions carrying their capability. Nexia-List is simply the first host. This is what makes an SDK, embedding, and the plugin ecosystem (LambdaDelta plugin system + dev design/deploy wizard (minter · provisioner · configurator · harness) #33) cheap rather than a later rewrite. A doc-test exercises the seam end-to-end.What's in this PR
reader.rs()[]{}#{},#uuid/#insttagged literals, sugar'`~~@,#(… % …),;comments, commas-as-whitespace. Guards sonan/inf/->stay symbols.value.rsnil/falsefalsy); reader-compatible printer; lexicalScopechain for closures.eval.rsquote if do let fn def+ quasiquote/unquote/unquote-splicing (spec §3); closures w/ lexical capture and& rest; keyword-as-function(:k m)(powers multimethod dispatch &sort-by); collection literals evaluate their elements.eval.rs)error.rsbuiltins.rsmap/filter/reduce/sort/sort-by), sets, strings, maps, reflection (eval/read/type). No notebook I/O — that's a host's job.wasm.rslambdadeltaEvalproves the kernel runs in the browser.Forks I resolved (flagged, not silent)
The spec left two things open; I picked and documented both in code:
=compares numbers across int/float ((= 1 1.0)→ true). Notebook attributes round-trip through JSON where2and2.0are indistinguishable in intent — strict variant-equality there is a quiet footgun.conj/conspreserve the natural structure.Deliberately deferred (to keep this reviewable)
Hygienic
defmacro+gensym/macroexpand; multimethods (defmulti/defmethod);let/fndestructuring; and the notebook host bindings (notes,set-attr!, …) a host registers through the seam. Each layers on top without changing the seam.Verification
cargo test— 66 green (34 kernel unit tests + 2 property tests [reader never panics on arbitrary input; print→read round-trip] + the existing core suite + the host-seam doc-test).cargo clippy --all-targets -- -D warnings— clean.cargo fmt --check— clean.cargo check --features wasm— clean (browser binding compiles).🤖 Generated with Claude Code
https://claude.ai/code/session_01PAEqVP7Y3bZDhtAaPUTbps
Generated by Claude Code