feat(core): LambdaDelta notebook host — λδ reads and mutates notes#36
Merged
Merged
Conversation
The moment λδ first touches a note. New `core/src/lambdadelta_host.rs` lives OUTSIDE the kernel (spec §7): the kernel stays note-agnostic, and this module registers the notebook builtins INTO a kernel through the seam (`Interp::register_builtin`). Nexia-List is simply the first host. Bridge (spec §2): - `note_to_value` renders a note as an immutable snapshot map (:id :title :content :attrs :links :backlinks :position :size :prototype :type :created-at :modified-at) with `#uuid`/`#inst` tagged ids/instants. - Total, lossless JSON attribute ↔ λδ value mapping (object keys ↔ keywords; documented lossy edges: keyword/set/symbol on write, functions → null). Builtins (spec §4): - Readers (pure): notes, note, title, content, attrs, links, backlinks, position, attr, search, resolve-title, agents, run-agent. Field accessors work on a note *map* (as `self`) or an id, so formulas read `self` directly. - Mutators (`!`): create-note!, set-title!, set-content! (derives [[wiki-links]]), set-attr!, remove-attr!, move-note!, resize-note!, link!, unlink!, delete-note!. Effects are id-based and return the updated note map; errors are values. WASM: `WasmNotebook::evalLambdadelta` runs notebook-aware λδ in the browser — a thin wrapper over the seam (share the notebook, install the host, eval, reclaim). The pure `lambdadeltaEval` from L0 remains for host-free evaluation. This unblocks L1 formulas: the canonical example `(count (words (content (note (resolve-title "Alpha")))))` is a passing test. Verification: `cargo test` 79 green (9 new host tests + kernel + core suite + seam doc-tests); clippy `-D warnings` clean (default + wasm); fmt clean; `cargo check --features wasm` clean. Production code stays panic-free. 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 12:10
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
The moment λδ first touches a note. Building on the merged L0 kernel (#35), this adds the notebook host — the note-aware builtins registered into a kernel through the seam.
Critically, this preserves the kernel/host split (spec §7): the new code lives in
core/src/lambdadelta_host.rs, outsidecore/src/lambdadelta/. The kernel still knows nothing about notes; an embedder with a different data model would write its own host exactly like this one. Nexia-List is simply the first host.Bridge — a note becomes data (spec §2)
note_to_valuerenders a note as its immutable snapshot map::id :title :content :attrs :links :backlinks :position :size :prototype :type :created-at :modified-at, with#uuid/#insttagged ids and instants.Builtins (spec §4)
notesnotetitlecontentattrslinksbacklinkspositionattrsearchresolve-titleagentsrun-agent!)create-note!set-title!set-content!(derives[[wiki-links]])set-attr!remove-attr!move-note!resize-note!link!unlink!delete-note!Field accessors work on a note map (as
selfin a formula) or an id, so(content self)reads directly with no round-trip. Mutators are id-based, return the updated note map, and surface errors as values (unknown id →LdError::User).WASM
WasmNotebook::evalLambdadelta(src)runs notebook-aware λδ in the browser — a thin wrapper over the seam (share the notebook viaRc<RefCell>, install the host, evaluate, reclaim). The purelambdadeltaEvalfrom L0 stays for host-free evaluation.Why it matters
This unblocks L1 formulas. The canonical example is a passing test:
Verification
cargo test— 79 green (9 new host tests: formula-over-a-note, search,set-attr!/create-note!/link!/set-content!mutating the real notebook, note-map-as-self, unknown-id-errors; + the kernel & core suites; + seam doc-tests).cargo clippy --all-targets -- -D warnings— clean (default and--features wasm).cargo fmt --check— clean.cargo check --features wasm— clean. Production code stays panic-free.Next (per the agreed "1 then 2")
Host bindings first (this PR) → then finish the language core: hygienic
defmacro+gensym/macroexpandand multimethods (defmulti/defmethod). Also still deferred: evaluation-context gating (formula pure vs. action may-mutate, spec §5),let/fndestructuring.🤖 Generated with Claude Code
https://claude.ai/code/session_01PAEqVP7Y3bZDhtAaPUTbps
Generated by Claude Code