Hazel Work Dashboard
A copy of the Hazel Work Dashboard that Matthew runs on his laptop, published at most ten minutes after each change to its notes, and to the status from GitHub, which it reads every 15 minutes. Its localhost links work only there.
Updated 2026-11-03 16:45 MST, by ~/localhost-index/update.py (PR titles and status from GitHub).
History: every change to this page, each a commit of one file (^ticket(417): no longer a file a change), also pushed to matthewhammer/hazel-work-notes (public). Published at most ten minutes after each change to our notes, and to the status from GitHub (read every 15 minutes): matthewhammer.org/hazel/dashboard/. How we work with this page: agent-instructions.md. This is version 0.0.4: VERSIONS.md lists what each version has. Closed tickets: their own page. This page reloads itself when it changes (checked every 90 s while it is open).
📖 What Claude has written to Matthew, since 2026-08-27 (as far back as the session transcripts go): 6,017 replies, 1,311,319 words, ~91.8 h to read at 238 words a minute, 🎧 ~136.6 h to hear at 160; a reply takes ~55 s to read, ~82 s to hear. Today: 77 replies, 14,479 words, ~61 min to read, ~1.5 h to hear. Each ticket's replies and their times are in its log in data.json.
Current ticket: ^ticket(677)
hazel, Hazlet, embed: Hazel's tile editor in another page (embed-editable as a PR, and served for a report) · from Matthew, 2026-11-02, in chat: "Once we publish hazeljs and mudu as npm packages, can we use those here? So the reader can: * see the trap room and * edit the hazel script, with tiles, etc? https://matthewhammer.org/hazel/reports/034/" meeting 2026-11-04 🪷 blocked on Matthew
Started Tue Nov 3, 11:16 AM MST · elapsed
Tiles in a page. Part of ^ticket(675). Embed mode (#2719) shows a posted program in Hazel's tiles, read-only; the embed-editable branch (12 commits, no PR yet) makes it selectable and editable. Open its PR, stacked on #2719 (^report(34)'s step 2). Then serve it where a report's page can frame it: a branch build URL, a copy of the app's files beside the report, or a package of its own. To check: whether a CDN that serves npm packages serves the app's index.html as a page at all. The library package (^ticket(668)) does not include the app: hazel-lib.js has no editor.
Now: 11:16: begin all tickets still enqueued (Matthew, 11:13): 677, embed-editable's red CI fixed (99239a446e, CI running); in flight on GitHub too: ^ticket(666)'s fix and its test, #2635's deck check (^ticket(663)), Dress Up 0.0.476's speed run (^ticket(674), ^ticket(676)).
Work Queue (Active Tickets)
What we mean to do next, in order: a few tickets, not the backlog. We push a ticket onto the front or the back, and reorder as we go; a ticket leaves the queue when it closes. Each links to its full row in the backlog.
| Next | Ticket | Area | Ticket |
|---|---|---|---|
| 1 | ^ticket(666)meeting 2026-11-04 hazel performance meeting | hazel, performance: how much sharing is lost passing data to and from the eval worker | Sharing across the worker boundary. How much structure sharing and identity is lost as data goes to the worker and back, and what that… |
| 2 | ^ticket(665)meeting 2026-11-04 hazel performance meeting | hazel, performance: the cost of undo, and O(log n) per edit and per undo instead of O(N) | Undo in O(log n). Measure what an edit and an undo cost as the program grows, and design undo so each costs O(log n), not O(N). Today, on… |
| 3 | ^ticket(667)meeting 2026-11-04 hazel performance meeting | hazel, performance: why #2635's evaluator takes half dev's steps on the PerfBudgets program | Half the steps. Dev's new PerfBudgets test (#2678, Cyrus) counts the evaluator's trampoline steps on a fixed program: 206,834 on dev… |
| 4 | ^ticket(681)hazel performance | hazel, Hazlet, performance, report 34: convert JS values directly at the call boundary, and a report measuring what it saves | Convert JS values directly. ^report(34)'s What next, step 4: convert JS values directly into Hazel values at the call boundary, not through… |
| 5 | ^ticket(669)meeting 2026-11-04 hazel meeting | hazel, Hazlet, npm: the package's build (hazel-lib.js for node and the browser) | Hazlet package: the build. Part of ^ticket(668). A folder with package.json and the release bundle of hazel-lib.js from #2719 (one… |
| 6 | ^ticket(676)meeting 2026-11-04 hazel dress-up meeting | hazel, Hazlet, Dress Up: the trap room on another page (a deep link, then a messed-up-dress-up package) | The trap room outside the game. Part of ^ticket(675). First step, small: a link that opens the game at the trap room with its Scripting… |
| 7 | ^ticket(678)meeting 2026-11-04 hazel meeting | hazel, Hazlet, report 34: the report's page wires the room, the tiles and hazeljs | The wiring. Part of ^ticket(675), after ^ticket(676) and ^ticket(677). The report's page posts the trap room's module text (and Common's)… |
| 8 | ^ticket(673)meeting 2026-11-04 hazel meeting | hazel, Hazlet, npm: the name, license, versions and who publishes | Hazlet package: name and publishing. Part of ^ticket(668); decisions for Matthew, some for the meeting with Cyrus. (1) The name: unscoped… |
| 9 | ^ticket(683)hazel dress-up | hazel, Hazlet, dress-up: what a Hazel edit box gives over a JS one: typed completion and errors in place | Hazel edit boxes over JS ones. Two advantages to make real in Messed Up Dress Up's tiles, and to say in hazeljs's README: (1) type-directed… |
| 10 | ^ticket(655)tracking hazel | hazel: where things stand after merge day (2026-10-29), to keep track | Matthew's tracking ticket for the state of things at the end of merge day: what landed, what waits on whom, and what to pick up next.… |
| 🪷 Blocked on Matthew: waiting for his response | |||
| 11 | ^ticket(677) currentmeeting 2026-11-04 🪷 blocked on Matthew hazel meeting | hazel, Hazlet, embed: Hazel's tile editor in another page (embed-editable as a PR, and served for a report) | Tiles in a page. Part of ^ticket(675). Embed mode (#2719) shows a posted program in Hazel's tiles, read-only; the embed-editable branch (12… |
| 12 | ^ticket(664)meeting 2026-11-04 🪷 blocked on Matthew hazel performance meeting | hazel, the meeting with Cyrus on Wed 2026-11-04: a list of specific tickets to grind on together | Tickets for Wednesday. Find or create a list of specific tickets to work through with Cyrus. Two to start: (1) the cost of undo, and ways… |
Special minutes
Each time Matthew had to remind Claude to keep going (his rule, 2026-10-20): 18 so far, 175 minutes idle in all. Newest first.
| When | His words | What Claude had stopped on | Idle |
|---|---|---|---|
| Mon Oct 26, 6:05 PM | “keep going” | ^ticket(637): sent mid-turn, while closing it (0.0.460 speed run green 18:03) | 2 min |
| Mon Oct 26, 1:22 PM | “go” | 0.0.459 released; every open ticket but 616 blocked on Matthew, 616 waiting on #2597's deck run | 25 min |
| Thu Oct 22, 7:42 PM | “AFK -- keep going.” | ended the turn on a question (Auto-fix for Adapton/fumola#150, which he then turned on) while 559's counter-build timing run and the no-counter build's Deploy ran in the background | 1 min |
| Thu Oct 22, 12:05 AM | “AFK -- keep going please.” | ended the turn after posting 531's results; only 0.0.408's speed run was left running | 0 min |
| Wed Oct 21, 11:51 PM | “AFK -- keep going please.” | ended the turn after starting 527's archive run; everything else was waiting on GitHub | 0 min |
| Wed Oct 21, 10:55 PM | “AFK -- keep going please.” | ended the turn after re-arming the PR watch; waiting on GitHub (521's final measurement, 531's comparison) with 527 not before 23:47 | 0 min |
| Wed Oct 21, 10:15 PM | “AFK -- keep going please.” | had just started 531's workflow and ended the turn; nothing else was startable (521 waiting on GitHub, 527 not before 23:47) | 0 min |
| Wed Oct 21, 9:22 PM | “AFK -- keep going please.” | ended the turn after re-arming the PR watch while three GitHub runs went, instead of building 521's c7 (the chip box) and c8 (People in boxes) | 30 min |
| Wed Oct 21, 7:15 PM | “did you stop? special time?” | ended the turn after pushing 521's c2/c3 while workflows and CI ran, instead of starting the next movable piece (518's prep, 517's furnishings plan, or 526's rename check) | 0 min |
| Wed Oct 21, 6:53 PM | “keep going, don't wait on me” | ended the turn with a status report while five workflows ran, instead of starting the next queued ticket (518) | 0 min |
| Wed Oct 21, 6:52 PM | “continue. / special time entry.” | ended the turn after the resume (and a /compact) while five workflows ran, instead of reviewing the commits they had already made (523 at 0aed09b, 520 B at cf9206c) | 6 min |
| Wed Oct 21, 4:04 PM | “have you stopped? is this special time?” | ended the turn after minting ^ticket(522), waiting on background work (the round-room workflow 516, hazel.org serving #2719's embed build for 520, 0.0.398's speed run) instead of starting the next unblocked work | 13 min |
| Tue Oct 20, 11:18 PM | “http://localhost:8000/ isn't up --- very special.” | at 22:22 I said the servers had survived the app's restart, from ss alone (ports listening); the five the app had started (8000, 8131, 8133, 8361, 8482) were alive but answered nothing, their log pipe gone with the app. Restarted 23:17; all eight ports answer | 56 min |
| Tue Oct 20, 11:17 PM | “keep going. AFK.” | reported the dashboard update and ended the turn, with 0.0.394's speed run and PR ^ticket(1)'s tests still on GitHub and no next ticket taken | 4 min |
| Tue Oct 20, 10:15 PM | “Why are you "stopped" -- ? The opposite of what I want now.” | held still after writing ^ticket(508), reading his 'Please stop.' (said while I relaunched watchers on coming back) as stop all work, though the CI runs, the archive run and the agenda could move | 0 min |
| Tue Oct 20, 10:12 PM | “Keep going.” | the archive-494c push: the shell was killed (exit 137) right after it went through, and the session ended there; the archive run had started on GitHub | 2 min |
| Tue Oct 20, 9:18 PM | “why did you stop....AGAIN?” | Ended the turn at 21:17 while my own two fixer agents (^ticket(507): farm502's drag, pasture503's horse size) ran in the background, instead of checking both in the browser pane myself meanwhile: the same mistake as 20:00, with my own agents in place of CI. | 1 min |
| Tue Oct 20, 8:35 PM | “why did you stop working?” | Ended the turn after reading 0.0.390's speed run and fixing horse438, to wait for 0.0.392's speed run (OBJECTS.md, ^ticket(494)), though the queue had work that needed no run (^ticket(387)'s visual check, done after the reminder). | 35 min |
Localhost ports
Every port this laptop serves, and every ticket waiting on Matthew, in the order we would like him to look.
🪷 Blocked on Matthew's decision (63)
Every open ticket tagged blocked on Matthew, the ones we most want looked at first.
| # | Ticket | What you decide | Where to look |
|---|---|---|---|
| 1 | ^ticket(600)dress up reports: ^du_report(18), the 🎬 story scripts and 🚶 paths, a guide for the kids with examples, and a zine with more coloring pages | M and N: read ^du_report(18) and the zine, color a page; their feedback, then the work-in-progress mark comes off. Matthew 10-24: maybe by tomorrow; they are not playing with the game right now. | — |
| 2 | ^ticket(389)hazel, meetings (Cyrus, Wed 2026-10-21) | Matthew: what the Cyrus meeting decided (to record in the agenda, ^report(20)) | — |
| 3 | ^ticket(465)hazel, the meeting with Cyrus on 2026-10-21: the plan | Matthew: what the Cyrus meeting decided (to record against the plan) | — |
| 4 | ^ticket(468)hazel, Gamma: a type in full, on several lines | Matthew (also agenda item 4): which way to offer Γ's unfold: always (the default), on hover, or by right-click? The setting is ^unfold on the Colors slide. Try it on 8312 (0113e420d0), or 8311 (#2597 at 2cd7b96f24, which has the same setting). | — |
| 5 | ^ticket(395)hazel, types, right-click to expand a type | Matthew: the exploration is on the ticket; pick: a box above vs expansion in place, #2635 (refractors) vs dev (inspector, Γ), one level per click vs all; then a prototype. | — |
| 6 | ^ticket(539)hazel, JS library: the call boundary's floor (of_js to final values, no re-step; a cheaper Id.mk) | Matthew: open lib-floor (the call's argument bound in the environment, floor -40%, CI green) as a PR stacked on #2719? | matthewhammer.org/hazel/reports/025/ |
| 7 | ^ticket(558)hazel js library: keep closures whole across the library, for real: a branch off lib-floor and a PR (^report(29) What next, step 1) | after ^ticket(539) (lib-floor as a PR on #2719?): open lib-closures as a PR stacked on it? | http://matthewhammer.org/hazel/reports/029/#step-1 |
| 8 | ^ticket(587)hazel: the JS library and embed expose modular editors' outline and navigation, for the game's ⛶ script view | Say whether the game should load lib-outline-587's build (its outline types then come from Hazel), and whether that branch goes into #2719 / #2711. | — |
| 9 | ^ticket(481)hazel, a draft PR: Hazel as a JS library | Matthew: push js-library-tagcheck (a bare tag from JS checked against a sum) to #2711, or leave it; the mountable editor waits on the meeting's word on the direction (^report(20) item 12). | hazelgrove/hazel/pull/2711 |
| 10 | ^ticket(574)hazel modules: a module exports its sum types' constructors, so other modules can use them (a PR against the modules PR), the game's Common | #2729 now waits on 7h3kk1d's review (follow-on tests in #2749, issue #2751 filed). Still yours: whether to post the note to Alexander on #2495. | — |
| 11 | ^ticket(484)hazel, #2613 (Colors): its review | Matthew: re-request review from 7h3kk1d on #2613 and resolve the label-header suggestion thread (CI green, mergeable, 0 behind dev); the --G5 pill (style.css:402) stays @disconcision's call. | hazelgrove/hazel/pull/2613 |
| 12 | ^ticket(485)hazel, #2583 (Deep links): the agreed refactor, and dev | Matthew: re-request review from 7h3kk1d on #2583 (green, mergeable, 0 behind dev at 077a68f9f8; his 12 threads still unresolved); optionally reverse Copy URL in every mode, or selection-or-caret. | hazelgrove/hazel/pull/2583 |
| 13 | ^ticket(541)hazel, #2681: is #2661 a real dependency, and should #2681's base be #2661's branch? (Alexander's suggestion) | Matthew: share ^report(26) with Alexander; and the merge-and-retarget of #2681, on your word. | hazelgrove/hazel/pull/2681 |
| 14 | ^ticket(572)hazel: new reviews on our open PRs, not yet integrated: a WIP report (one, with a subsection per PR) for Matthew's review | Read ^report(31) at https://matthewhammer.org/hazel/reports/031/ (public since 10-23 14:13) and say which reviews to answer first: #2608 (changes requested 10-21) and #2651 (Alexander's question of 10-23) have had no reply. | localhost:8131/031/ |
| 15 | ^ticket(521)dress up, panels: knolling the whole panel system again; ^du_report(16) against ^du_report(5), the whitespace before and after, a PR | see the ticket | localhost:8133/report-016/reports/016/ matthewhammer.org/kids-choice-games/dress-up/reports/016/ |
| 16 | ^ticket(160)dress up, performance, touch, testing | Tonight, on the iPad and the Ubuntu laptop: open https://matthewhammer.org/kids-choice-games/dress-up/ (0.0.429), ⚙️ Advanced, 🧪 this computer's speed (about 76 s, hands off), then 📋 copy the line and paste it here. Its 🌲 part puts the forest by a controller and by holding the on-screen arrows side by side. | matthewhammer.org/kids-choice-games/dress-up/reports/001/ |
| 17 | ^ticket(589)fumola: expose the Core state's vm_defs (the definition outline) through the wasm API, for the game's ⛶ outline | Say whether to open PRs for defs-parse-590 and wasm-defs-589 on Adapton/fumola (then the game pins the new build and its outline reads Fumola's defs). | — |
| 18 | ^ticket(590)fumola: keep parse information for every AST form in the Core's definitions (types too), for ^ticket(589)'s API | Say whether to open a PR for defs-parse-590 on Adapton/fumola. | — |
| 19 | ^ticket(571)fumola semantics: fix the traps scripting the game found (^report(28) #traps): text != inverted, text patterns, Nat and Int, Float compariso | Review Adapton/fumola#151 (https://github.com/Adapton/fumola/pull/151); read the revised ^report(28) at http://localhost:8131/028/#traps, then say publish. | localhost:8131/028/#traps matthewhammer.org/hazel/reports/028/#traps |
| 20 | ^ticket(549)fumola wasm: an answer over ~1,000 deep crashes the instance (recursive JSON) | see the ticket | http://matthewhammer.org/hazel/reports/029/#step-4 |
| 21 | ^ticket(315)fumola.org, light mode | Matthew: OK to merge Adapton/fumola#147 (fumola.org's light theme)? Open, mergeable, build-and-test green (10-18 21:31Z), head 96f267f; merging to main deploys it (Publish wasm to Pages runs on push to main). | — |
| 22 | ^ticket(559)hazel evaluator: a fast path for terms already final, skipping the five stages when nothing is probed or reused (^report(29) What next, step | see the ticket | http://matthewhammer.org/hazel/reports/029/#step-5 |
| 23 | ^ticket(548)hazel evaluator: push a type through a list without minting an id per element (list loops are quadratic) | see the ticket | matthewhammer.org/hazel/reports/029/#re-type |
| 24 | ^ticket(551)hazel js library: handles, so a big JS value crosses once (Hazel.value(x) and an identity cache) | see the ticket | matthewhammer.org/hazel/reports/027/#fig-sizes |
| 25 | ^ticket(552)hazel js library: a complexity test, so a call's cost stays independent of what it holds | see the ticket | matthewhammer.org/hazel/reports/029/#re-walk |
| 26 | ^ticket(547)hazel js library: keep closures whole across the boundary (a held value costs O(size) per call from JS) | see the ticket | matthewhammer.org/hazel/reports/029/#re-walk |
| 27 | ^ticket(550)hazel evaluator: a term already known to be a value evaluates in O(1) (a value memo) | see the ticket | matthewhammer.org/hazel/reports/029/#re-walk |
| 28 | ^ticket(553)hazel: a map for Dress Up's rules, and the World rule timed with it (^report(27) What next, step 2) | see the ticket | matthewhammer.org/hazel/reports/027/#step-2 |
| 29 | ^ticket(545)hazel × fumola: why the same rule runs 2.4x to 10x faster in Fumola: steps, cost per step, the boundary, wasm vs js (a report, work in progr | see the ticket | matthewhammer.org/hazel/reports/029/ |
| 30 | ^ticket(588)hazel reports: ^report(32), the 📜 Scripting tab's speed run with JS, Fumola and Hazel as the default | Review the draft at http://localhost:8131/032/#correct (not public: matthewhammer.org/hazel/reports/032/ is a 404 until you say publish). | localhost:8131/032/#correct localhost:8131/032/ |
| 31 | ^ticket(570)hazel reports: two days of game scripts in Hazel for MUDU, since the 10-21 meeting: where we are against the goal | Read the ^report(30) draft at http://localhost:8131/030/ : the code boxes at http://localhost:8131/030/#rules and the Languages of Play section at http://localhost:8131/030/#lop; then say publish. | localhost:8131/030/ localhost:8131/030/#rules localhost:8131/030/#lop |
| 32 | ^ticket(533)hazel, performance: what a call into Hazel costs (^report(25), from Dress Up's ^ticket(531)) | Matthew: look at the draft (localhost:8131/025/#code): do the tile boxes draw in your browser (click 'show Hazel's tiles'; the line beside it says how far it got)? | matthewhammer.org/hazel/reports/025/ |
| 33 | ^ticket(537)hazel, JS library (#2711, #2719): a review of it, in ^report(25), as this report uses it | Matthew: read the library review in ^report(25): https://matthewhammer.org/hazel/reports/025/#library | matthewhammer.org/hazel/reports/025/ |
| 34 | ^ticket(538)hazel, JS library: tiles in a page that show reliably (a read-only mount without a frame, or a frame that draws off screen) | Matthew: in ^report(25)'s tile boxes (https://matthewhammer.org/hazel/reports/025/#code), click in the tiles, then drag or use the arrows: do the tile shapes show? Then: propose embed-selectable on #2719? | matthewhammer.org/hazel/reports/025/ |
| 35 | ^ticket(398)hazel, performance, correctness: the #2609 PRs | Matthew: read the ^report(21) draft (http://localhost:8131/021/); publish on his word. The tests half is ^ticket(411). Also: report 21's draft source is already in the public repo by mistake; leave it, or remove it (a force push)? | localhost:8131/021/ |
| 36 | ^ticket(408)hazel, Hazel Weekly: how its agent credits the team | Matthew: read ^report(22) (localhost:8131/022/): publish it, and/or pass the ten corrections to Andrew? | localhost:8131/022/ andrewblinn.com/hazel/weekly/ |
| 37 | ^ticket(573)hazel reports: a 🔊 Listen button on every report, read by the reader's own browser voice | Try 🔊 Listen on any report draft, e.g. http://localhost:8131/030/ (a device with voices: Mac, iPad, desktop Chrome), then say republish all. | localhost:8131/030/ |
| 38 | ^ticket(411)hazel, correctness tests for the performance PRs (a PR to dev) | Matthew: the Cyrus meeting's word: which of the 19 PRs get their own tests first, and who reviews #2700? | — |
| 39 | ^ticket(470)hazel, performance: opening each documentation slide, timed on GitHub | Matthew: the Cyrus meeting's word: keep the slide-timing job running per PR and on dev? | — |
| 40 | ^ticket(388)hazel, the syntax explainer (RHS) | Wednesday's meeting: one shared read-only, selectable view for every look-only surface (as ^report(19) suggests), or the explainer's examples alone first? | — |
| 41 | ^ticket(462)hazel, #2635: Fumola out, into its own PR | Matthew: #2650 (Fumola, shelved) is red at 69b8509173 (run 39481873576); your 07:38 ask said CI green for all three, so: fix it, park it, or close it? And close #2616? Its head c4ec888b82 is inside #2650. | — |
| 42 | ^ticket(16)CI | see the ticket | http://localhost:8131/series/006/#today |
| 43 | ^ticket(17)performance, CI | see the ticket | http://localhost:8131/series/006/#pr2161 |
| 44 | ^ticket(18)performance | see the ticket | http://localhost:8131/series/005/#where |
| 45 | ^ticket(102)hazel | see the ticket | hazelgrove/hazel/pull/2583#issuecomment-6197659505 |
| 46 | ^ticket(401)hazel, livelits, #2635: pictures full screen | Matthew, on your own machine (not 8341: this laptop's worker times out on Scenes at the fixed 20 s eval_timeout_ms, still 20000 on 9933091a99): open the Scenes slide on #2635's public build, hazel.org/build/integration/livelits-modular-editors/ (the same code as 9933091a99), click the full-screen button at the top right of the drawn picture, and press Esc to leave. | http://localhost:8341/?slide=livelit-playground-scenes |
| 47 | ^ticket(166)dress up, fumola, infrastructure | Matthew: whether to build the family-only access first (Claude's part, per 07:00 10-17), then deploy to mainnet (your cycles); or to deploy the open telemetry log now, as the pad is. | pad.riseup.net/p/LgBrn8VRzEJxrsmMW82I |
| 48 | ^ticket(276)dress up, archives | Matthew: make a fine-grained token (resource owner matthewhammer; only the repositories dress-up-pictures and dress-up-music; permission Contents: Read and write), then add it to matthewhammer/kids-choice-games as the Actions secret ARCHIVE_TOKEN (Settings, Secrets and variables, Actions; or: gh secret set ARCHIVE_TOKEN -R matthewhammer/kids-choice-games). The next archive run then lands by itself. | matthewhammer.org/kids-choice-games/dress-up/reports/004/#step-3 |
| 49 | ^ticket(397)operations, the work laptop: its battery | Matthew: reseat the battery's connector; if the kernel still sees no battery, replace it (maybe also a stronger USB-C adapter and cable). Then Claude checks journalctl, upower and the clock. | matthewhammer.org/hazel-work-notes/crash-log.html |
| 50 | ^ticket(534)operations: move our work to the spare laptop from Cyrus, so this one can be fixed | Cyrus: send the spare laptop (Matthew expects it in about two weeks). Matthew: set it up, then move our work onto it. | matthewhammer.org/hazel-work-notes/crash-log.html |
| 51 | ^ticket(423)dashboard, hazel-work-notes: a weekly git gc | see the ticket | — |
| 52 | ^ticket(429)matthewhammer.org, its repository: the dashboard's history in it | see the ticket | — |
| 53 | ^ticket(591) (not ranked yet)hazel #2711 (Hazel as a JS library): unit tests seeded from the game's real scripts and their JS equivalence | Say whether to merge js-library-591 into #2711 (js-library). | — |
| 54 | ^ticket(602) (not ranked yet)operations, the Claude desktop app: after its window hung it stayed gone until a reboot (2026-10-24); reinstalling did not help | Only if you want Anthropic to know: report that the desktop app's own kill-and-reload never brought its window back (in the app's Help menu, or an issue on github.com/anthropics/claude-code); this ticket has the times and log lines. Otherwise close it. | — |
| 55 | ^ticket(609) (not ranked yet)hazel reports: writing MUDU's game scripts: Globals as it is (a per-rule view), RoomState, a full Globals as a Hazel type, and one address f | Read on in ^report(33), Game Scripts in Hazel, a Case Study (work in progress): https://matthewhammer.org/hazel/reports/033/ , and send the next notes. | — |
| 56 | ^ticket(611) (not ranked yet)dress up: a 🌍 Start World button beside Start over: the start world's start square, the friend put there, and a pop-up saying what the game | R: try 🌍 Start World on his phone (0.0.433+); his feedback goes into ^du_report(20), then its WIP mark comes off | — |
| 57 | ^ticket(633) (not ranked yet)dress up: ^du_report(21), the dungeon rooms and the friend from every side: every costume from above (front, side, back) and asleep in the t | see the ticket | — |
| 58 | ^ticket(634) (not ranked yet)dress up: agent-instructions.md cut from 380 KB to a short checklist; the explanation moved to a new public report, ^du_report(22), readable | see the ticket | — |
| 59 | ^ticket(635) (not ranked yet)hazel reports: ^report(34), the pros and cons of an official Hazel JS library (#2711, #2719): for game scripting (MUDU's 📜 rules) and for ot | see the ticket | — |
| 60 | ^ticket(642) (not ranked yet)hazel: the landing order for livelits — #2469 to dev first, then retarget #2635 to dev | Post the end-of-day Slack draft (~/hazel/experiments/slack-end-of-day-2026-10-29.txt): it asks Cyrus whether #2469 into dev, then #2635 retargeted onto dev, still works. | — |
| 61 | ^ticket(654) (not ranked yet)hazel merge day (10-29), end of day: your approvals and the Slack post | Approve https://github.com/hazelgrove/hazel/pull/2756 and https://github.com/hazelgrove/hazel/pull/2626 (LGTM notes on ^ticket(652), ^ticket(653)); then post ~/hazel/experiments/slack-end-of-day-2026-10-29.txt to Slack. | — |
| 62 | ^ticket(664) (not ranked yet)hazel, the meeting with Cyrus on Wed 2026-11-04: a list of specific tickets to grind on together | Your answers to the agenda's questions for Wednesday's meeting with Cyrus (you said this morning you had some). | localhost:8131/037/ |
| 63 | ^ticket(677) (not ranked yet)hazel, Hazlet, embed: Hazel's tile editor in another page (embed-editable as a PR, and served for a report) | Your call on folding #2719 into #2711 (one PR for hazeljs), which decides the base of embed-editable's PR. | — |
Livelits and Γ's types (3)
The two livelits PRs (#2635, #2597) and Γ's long types to try (^ticket(468)); on the agenda of the 10-21 meeting with Cyrus.
| PR # and title | Repo and branch | Localhost |
|---|---|---|
| #2635 Livelits × modular editors: merge #2469 into the livelits branch | hazelgrove/hazelintegration/livelits-modular-editors | localhost:8341 (#2635 at 547b9cfa8b: GitHub's build deployed 10-27; the head is 1d17541aaf) #2635's Scenes slide |
| #2597 User-Defined Livelits, as in PLDI '21, and beyond. | hazelgrove/hazelintegration/livelits-splicerefs-full | localhost:8311 (#2597 at 5aab038ff5: GitHub's build deployed 10-25; the head is c7f9249802) |
| — Γ's long types by right-click or hover (^ticket(468), to try) | hazelgrove/hazel, trial/468-gamma-unfoldtrial/468-gamma-unfold NOT SERVED since 11:50 on 2026-10-24: stopped for 8131 (Matthew's call; the app runs at most five servers per worktree). Its launch entry "#2597 + #2698 GitHub build (trial/468-gamma-unfold)" brings it back. ^ticket(468) waits on it. (served since 10:25 on 2026-10-20: GitHub's build of 0113e420d0, #2597 plus Γ's unfold from #2698, its right-click menu, and the Colors slide's choice of how the toggle is drawn; Fast checks green. A fresh port, so the shipped Colors slide (Configuration, in the top bar's mode menu; the always / hover / right-click choice at its top) is what loads. The setting has been on both PRs since 12:51 10-20; Matthew's pick of the default is left.) | not served |
Other ports open (3)
Everything else served on this laptop, to show the work.
| PR # and title | Repo and branch | Localhost |
|---|---|---|
| — Hazel reports (the report's sources) | matthewhammer/hazel-reports, checked out at ~/hazel-perf-reportmain NOT SERVED since the crash at about 09:04 on 2026-11-03 (crash 48); Matthew, 09:20: no need to restart local builds for now. (first served 2026-10-24 in place of 8312, Matthew's call; every link here and in the open tickets checked, anchors too. Open tickets waiting on its drafts: ^ticket(398), ^ticket(408), ^ticket(533), ^ticket(570), ^ticket(571), ^ticket(572), ^ticket(573), ^ticket(588).) Its sources are 36 commits ahead of origin (drafts wait there); ^report(37), the agenda, and ^report(36) go out by the homepage. (public: a push publishes, so drafts wait. ^report(25) published as work in progress 10-22 09:44 (homepage 35951cb); its local copy is the same. ^report(18), why #2635 fails CI, is a local draft waiting on Matthew. ^report(29) republished 10-22 15:56 (homepage e9fd165) with its fixes section and the deep-answer correction; its local copy is the same); its local copy is the same; its fixes section fills in as the trial builds are measured) | localhost:8131 (the front page: every report, drafts marked) localhost:8131/037/ (^report(37), the agenda for 11-04; published 07:38 with links to 38 and 39; local and public the same) localhost:8131/038/ (^report(38), Undo, in Time and Space: published; local and public the same) localhost:8131/034/#try (^report(34): the trap room live on the page, published) localhost:8131/039/ (^report(39), Hazlets, So Far; work in progress, published 11-03) localhost:8131/036/ (^report(36), What an Undo Costs; work in progress, published) localhost:8131/032/ (^report(32) draft: Scripting, Three Ways, Timed) localhost:8131/031/ (^report(31), Reviews Still Open) localhost:8131/030/ (^report(30), Game Scripts in Hazel; its Hazel and Fumola rules, Languages of Play) localhost:8131/029/ (^report(29), Where the Gap Comes From; second fixes) localhost:8131/028/ (^report(28), the traps and proposed fixes) localhost:8131/025/ (^report(25), Hazel's JS library) |
| — Messed Up Dress Up (the game) | matthewhammer/kids-choice-games, folder dress-up/, public with its history from 2026-10-09Its own Pages site deploys every push to main. Edit ~/kids-choice-games: ~/hazel/experiments/polygons-plain/dress-up.html is a symlink to it.main NOT SERVED since the crash at about 09:04 on 2026-11-03 (crash 48); Matthew, 09:20: no need to restart local builds for now. (the working copy of main, ~/kids-choice-games, served again since 08:45 on 2026-11-01 after the reboot. Matthew's uncommitted ^du_report(5) edits are in the working tree, left as they are (his call, 10-29); an old autostash sits in git stash@{0}.) | localhost:8133/dress-up.html (0.0.475, main: pushed and tagged; ?try=trap&logic=hazel opens the trap room) localhost:8133/dress-up/?try=trap&logic=hazel (0.0.475: the trap room by link, ^ticket(676)) localhost:8133/report-024/reports/024/ (^du_report(24) draft: Night, Day and the Garden) localhost:8133/du-reports/ |
| — this dashboard | ~/localhost-index (data.json, update.py)local | localhost:8000 (the Hazel Work Dashboard, this page; public copy at matthewhammer.org/hazel/dashboard/) |
Other PRs we are tracking
Not about performance: features, fixes, docs, CI.
| PR # and title | Branch → base | State | CI | Review | Merge | Updated | Note |
|---|---|---|---|---|---|---|---|
| #2700 Test: incremental evaluation agrees with evaluation from scratch, on recursive lets and over the slide corpus | test/incremental-matches-fresh → dev | merged | ✓ 5 passed | approved | unknown | 2026-10-29 | Tests PR to dev, ready for review since 13:33 10-20, no reviewer requested (the agenda asks) (^ticket(411), from ^report(21)): incremental evaluation agrees with evaluation from scratch: the property back on for values, recursive-let templates, and the slide corpus (150 edits). Mutation-checked. |
| #2699 non-`dev` (`integration/livelits-modular-editors`): Exploratory: per-member module analysis on Modules II, after Andrew's stdlib port | explore/2635-per-member-modules-ii → integration/livelits-modular-editors | merged | ✓ 5 passed | no review yet | unknown | 2026-10-19 | Exploratory DRAFT into #2635 (^ticket(400)): per-member module analysis on Modules II, Andrew's stdlib port (a6b5478f52 / 00bc805ca1) fitted to #2635. 12:06 10-19: #2635's 1131a457e4 merged in and its own corpus failure (color-fig3.hz, livelit definitions taken for modules) fixed in 223357135a: DefStaticsParity 43 of 43 locally. Merging it into #2635 is Matthew's call. |
| #2676 The cursor inspector can show a long type whole, on several lines | cursor-inspector-full-types → dev | open | ✓ 5 passed | review required | mergeable | 2026-10-29 | The type-expansion panel (issue #2674). Its fix for module signatures' parentheses is only on #2635: dev prints a signature as a labeled tuple. |
| #2698 non-`dev` (`cursor-inspector-full-types`): Gamma can show a long type whole, on several lines | context-inspector-long-types → cursor-inspector-full-types | draft | ✓ 5 passed | no review yet | mergeable | 2026-10-19 | Draft, stacked on #2676 (^ticket(386)): Gamma's long types. Not served on its own since the 10-24 reboot; its unfold is in the build on localhost:8312 (^ticket(468)). |
| #2583 Deep links: the URL can say which slide, which panel, and where the cursor is | deep-links → dev | open | ✓ 5 passed | ⚠️ changes requested | mergeable | 2026-10-29 | |
| #2613 Colors: every var() a stylesheet reads is one the theme defines | configuration-undefined-colors → dev | open | ✓ 5 passed | ⚠️ changes requested | conflicts | 2026-10-20 | |
| #2605 Substitution: a let's definition sees the outer binding, not its own | substitution-let-def-scope → dev | open | ✓ 5 passed | review required | mergeable | 2026-09-27 | |
| #2608 Leave the source's whitespace and comments out of elaborations | elab-no-secondary → dev | open | ✓ 5 passed | ⚠️ changes requested | mergeable | 2026-10-21 | |
| #2592 Report each error once, not once per wrapper | error-dedup-wrappers → dev | draft | ✓ 5 passed | review required | mergeable | 2026-09-23 | |
| #2491 docs: research-paper implementation status report | docs/research-status-report → dev | closed | ✓ 7 passed | review required | mergeable | 2026-10-29 | Docs. |
| #2577 Serve the release web build from an Internet Computer canister | ic-canister → dev | draft | ✓ 7 passed | review required | conflicts | 2026-09-22 | |
| #2616 non-`dev` (`integration/livelits-splicerefs-full`): Remote refs: splices a Fumola instance reads and writes | remote-splices → integration/livelits-splicerefs-full | open | ✗ 2 failing: checks / Fast checks (failure), checks / Full tests (failure); ✓ 1 passed | no review yet | conflicts | 2026-10-04 | Remote splices, into #2597's branch. Superseded by #2650, which holds its commits and since 13:15 10-20 targets #2635's branch (^ticket(462)); red, and closing it is Matthew's call. |
| #2650 non-`dev` (`integration/livelits-modular-editors`): Hazel's state and Fumola instances on an Internet Computer canister | ic-canister-fumola → integration/livelits-modular-editors | open | ✗ 2 failing: checks / Fast checks (failure), checks / Full tests (failure); ✓ 1 passed | no review yet | conflicts | 2026-10-20 | The IC canister demo and the Fumola work moved out of #2635 (^ticket(462)). Into #2635's branch since 10-20; red at 69b8509173; shelved, Matthew's call. |
| #2536 non-`dev` (`integration/modules-livelits`): experimental language integrations | experimental-lang-integration → integration/modules-livelits | draft | ✓ 5 passed | no review yet | mergeable | 2026-09-22 | Fumola-in-Hazel, shelved since 2026-09-16 (its issues go to Adapton/fumola). |
Repositories we deploy
Pushed to directly, without PRs. The version is the newest in each project's VERSIONS.md. Deployed means Pages has built the branch's latest commit; a repository without a Pages site runs where its links point.
| Repository and branch | Latest commit | Version | Deployed | Open PRs | Note |
|---|---|---|---|---|---|
matthewhammer/kids-choice-gamesmain | f6ef86b Dress Up speed, after the release: 0.0.478: ok (2026-11-03) | Messed Up Dress Up 0.0.478 (2026-11-03) | ✓ deployed f6ef86bMessed Up Dress Up localhost:8133/dress-up.html 🎵 the tunes (MP3s) | #3 Dress Up: less empty space in the panels: no empty columns, packed boxes, one chip for long choices (ticket 521) | The kids' toys, prototyped in plain JS with real players before the Hazel slides formulate them as user-defined livelits (#2635, #2597; ^report(1) on). Each version is tagged dress-up-X.Y.Z. |
matthewhammer/dress-up-picturesmain | e3c8820 2026/10/25/13-08: Messed Up Dress Up 0.0.439 (2026-10-25) | — | ✓ deployed e3c8820every picture, by day localhost:8133/screenshots/ | none | The Dress Up picture archive, apart from the game (^ticket(106)): each day, every background and chip menu at its defaults, as PNG + SVG + settings. Unchanged files are symlinks to the day they last changed. ~/du-shots/tools/archive-today.sh makes a day. |
matthewhammer/dress-up-musicmain | 765cadf 2026/10/18/23-14: Messed Up Dress Up 0.0.304 (2026-10-19) | — | ✓ deployed 765cadfevery tune, by day localhost:8133/music/ | none | The Dress Up music archive, apart from the game (^ticket(106)): each day, every tune at its defaults, one loop each, as MP3. Unchanged tunes (by fingerprint) are symlinks to the day they last changed. |
matthewhammer/hazel-work-notesmain | 50c0dcf Dashboard 2026-11-03 16:30 MST: index.html (2026-11-03) | Hazel Work Dashboard 0.0.4 (2026-10-23) | ✓ deployed 50c0dcfthe dashboard, published the dashboard, localhost:8000 its history, localhost:8000/notes/ | none | This page's code (dashboard/, run in place: ~/localhost-index links to it), its history and agent-instructions.md. PUBLIC since 2026-10-13. Since 2026-10-16 (^ticket(181)) the public copy of this page (noindex) is at matthewhammer.org/hazel/dashboard/, in the homepage's repository: site_publish.py commits it there at most every ten minutes, without touching the homepage's checkout (so pull there before pushing). This repository's root and matthewhammer.org/hazel/work-dashboard/ redirect to it. Cron commits and pushes a snapshot and data.json here when the page changes; the code is committed by hand. |
matthewhammer/hazel-performance-analysismain | fb780b2 Publish ^report(30), ^report(31) and the revisions of 28 and 29; the series index at the root (^ticket(576)), report 1 in 001/, draft cards for the local preview (2026-10-23) | — | no Pages site the series, published drafts, localhost:8131/series/ | none | The performance analysis series, for outside readers (^report(1) on), with its history since 2026-10-09 and its own agent-instructions.md. Public since 2026-10-12. Published by copying a report to the homepage repo; a push here is public too, so drafts wait for review. |
Performance Analysis and Improvement
Tracked in hazelgrove/hazel#2609 (performance challenges). Write-ups: the performance analysis series (local sources).
Performance PRs
Against #2609; the last three (#2606, #2603, #2490) are from before it.
| PR # and title | Branch → base | State | CI | Review | Merge | Updated |
|---|---|---|---|---|---|---|
| #2689 Test: statics analyzes each expression within a budget | ci/statics-passes-dev → dev | draft | ✓ 5 passed | review required | mergeable | 2026-10-17 |
| #2690 Test: a re-run beside a library with recursive members stays within its step budget | ci/recursive-let-budget → dev | draft | ✓ 5 passed | review required | conflicts | 2026-10-21 |
| #2691 Test: what the eval worker sends and gets back stays within a byte budget | ci/byte-budgets → dev | draft | ✓ 5 passed | review required | mergeable | 2026-10-17 |
| #2681 A value known to have a type is not walked again for it | ascriptions-has-type → dev | open | ✓ 5 passed | review required | conflicts | 2026-10-29 |
| #2679 An ascription pushed through a value gives the value back when it already has the type | ascriptions-copy-on-change → dev | merged | ✓ 5 passed | approved | unknown | 2026-10-19 |
| #2678 CI fails when an evaluation does more work than its budget | ci-perf-budgets → dev | merged | ✓ 5 passed | approved | unknown | 2026-10-29 |
| #2675 Incremental evaluation reuses expressions around a recursive let | recursive-let-reuse → dev | open | ✓ 5 passed | review required | mergeable | 2026-10-29 |
| #2673 Incremental evaluation recognizes an unchanged expression by its Merkle hash | reuse-check-merkle-hash → dev | open | ✓ 5 passed | review required | mergeable | 2026-10-20 |
| #2661 Types get a Merkle hash; the evaluator asks is_consistent once per pair | typ-hash-consistent → dev | open | ✓ 5 passed | review required | conflicts | 2026-10-29 |
| #2651 Statics: a module binding analyzes its definition once, not twice | statics-module-def-once → dev | open | ✓ 5 passed | review required | mergeable | 2026-10-29 |
| #2652 Eval worker in Firefox: start it at load, and do not time out a reply that is queued | eval-worker-start-at-load → dev | open | ✓ 5 passed | review required | mergeable | 2026-10-29 |
| #2614 Load text about 2.5× faster: whole tokens, one re-grout | parser-perf → dev | open | ✓ 5 passed | review required | mergeable | 2026-09-29 |
| #2610 Parse the load fallback with the segmented parser, projectors kept | parse-fallback-segmented → dev | open | ✓ 5 passed | review required | mergeable | 2026-10-20 |
| #2671 MapPiece keeps unchanged pieces as the same objects | mappiece-keep-identity → dev | open | ✓ 5 passed | review required | mergeable | 2026-10-10 |
| #2672 Measuring the font scrolls to the caret only if it was in view | font-metrics-keep-scroll → dev | merged | ✓ 6 passed | approved | unknown | 2026-10-29 |
| #2608 Leave the source's whitespace and comments out of elaborations | elab-no-secondary → dev | open | ✓ 5 passed | ⚠️ changes requested | mergeable | 2026-10-21 |
| #2606 Keep the incremental cache in the eval worker | eval-worker-held-cache → dev | open | ✓ 5 passed | review required | mergeable | 2026-09-30 |
| #2603 Statics: a let is analyzed once unless it refers to itself, plus three smaller speedups | dev-statics-perf → dev | open | ✓ 5 passed | review required | mergeable | 2026-09-26 |
| #2490 SPIKE: compile the Hazel evaluator with wasm_of_ocaml and benchmark it | wasm-eval-bench-spike → dev | draft | ✓ 7 passed | review required | conflicts | 2026-09-22 |
| #2793 Fewer trampoline bounces: half the evaluator's steps on the PerfBudgets program | perf/fewer-trampoline-bounces → dev | open | ✓ 6 passed | review required | mergeable | 2026-11-03 |
The integration branches also carry these fixes:
| PR # and title | Branch → base | State | CI | Review | Merge | Updated |
|---|---|---|---|---|---|---|
| #2635 Livelits × modular editors: merge #2469 into the livelits branch | integration/livelits-modular-editors → integration/livelits-splicerefs-full | draft | ✓ 10 passed | no review yet | mergeable | 2026-11-03 |
| #2597 User-Defined Livelits, as in PLDI '21, and beyond. | integration/livelits-splicerefs-full → integration/livelits-splicerefs | open | ✗ 1 failing: Deck in Firefox (failure); ✓ 5 passed | no review yet | mergeable | 2026-10-26 |
Full Backlog (All Tickets)
All our open tickets: important and not done; the few we mean to do next are in the work queue. Numbered in our own sequence from #1; a number is never reused. A closed ticket moves to the closed tickets, with how it ended.
| Ticket | Area | Text | From |
|---|---|---|---|
^ticket(16) | CI 🪷 blocked on Matthew meeting 2026-10-21 hazel | Ask the maintainers to require the test jobs for merging into dev: today no check is required, so a red budget is a signal, not a gate. | ^report(6) |
^ticket(17) | performance, CI 🪷 blocked on Matthew hazel performance | A timing report that informs and doesn't fail: base and head on one runner, repeated, phase by phase, perhaps from #2161's harness (David's call). | ^report(6) |
^ticket(18) | performance 🪷 blocked on Matthew meeting 2026-10-21 meeting 2026-11-04 hazel performance meeting | Option B from ^report(5): evaluate each livelit's view in the worker, keep the last Html sent per livelit, and post patches to it, so view evaluation leaves the main thread. Needs the view runner (ViewCmdRunner) in the worker, a patch format, an element on the page that owns each livelit's DOM and applies patches, and handlers dispatched by id. Keep the page's own path for an interaction's immediate redraw, or every drag waits a round trip. Its condition is now met (2026-10-12, see ^ticket(10)): evaluating the view is about 69% of the main thread in a woods figure move, and C would save about 2%. Weigh it against making the view itself cheaper first (^ticket(1), ^ticket(2)). PROTOTYPED 2026-10-14 (local branches, nothing pushed; work notes http://matthewhammer.org/hazel-work-notes/work-notes/2026/10/14/2026-10-14T2120-0600.html): MvuShape and ViewCmdRunner moved to the language library (61d031fd93, no change in behavior); the worker runs view commands to Html, reusing an unchanged view per projector (fast_equal), and whole programs fold their views in too (experiments on experiment/2635-views-in-worker-all, ede920b07e). Full Body: the main thread about 540 ms (UX mode) / 220 ms (whole program) less per change, the redraw no later; Kids' Choice: release about 45 ms later (144 → 187–196 ms). Waits for Matthew's design calls: which livelits' views move (all, or the costly ones), and the on-screen ids in the request. 2026-10-15T18:52: tagged 🪷 blocked on Matthew: its next step is his call (see above). | ^report(5) |
^ticket(102) | hazel 🪷 blocked on Matthew meeting 2026-10-21 hazel | Reply to Alexander on the deep links PR (#2583; Matthew writes the reply by hand). Alexander (7h3kk1d) replied today at 11:00 to our comment of 10-14 linking the plan page; he couldn't comment on that page, so he left his notes on the PR. His two points on the plan's sketch: (1) name `target`'s constructors `Documentation` and `Scratchpad`, not `Slide` and `Share`, and use records instead of tuples where there are several fields (`Scratchpad({name, share})`); (2) the `request` record allows a `position` without a `target`: he'd like a type that rules it out. Fact for the reply: on the branch as pushed (09-22), `?caret=` without `?slide=` puts the caret in whatever opens (the reader's last slide or scratchpad), so such a link depends on the reader's saved state. That supports nesting the position inside the place, e.g. `{place: option({target, position: option(position)}), panel: option(panel_request)}`. A panel-only link stays meaningful. Then revise the plan, and later the branch, to match whatever is agreed. He liked the rest. Also worth an answer: where he should comment on plans next time (the PR itself, or the PR description). 2026-10-15T15:59: tagged 🪷 blocked on Matthew (his reply, written by hand), at the end of the queue. | Matthew, 2026-10-15 |
^ticket(160) | dress up, performance, touch, testing 🪷 blocked on Matthew dress-up performance | Dress Up: audit every place with the on-screen controller: walk across each, at 60 frames a second. Matthew, 2026-10-16, to follow ^ticket(158) (the living room, the empty room and the imagination with the on-screen controls): for each of the 24 places (and the castle's room styles and the tree house's rooms), hold the on-screen ◀ ▶ (and ▲ ▼) to walk the friend across it, measure frames a second, and fix or make optional (⚙️ Advanced, off by default) whatever keeps one under 60. The gate's coverage grows by what this finds (^du_report(1), What next). | Matthew, 2026-10-16, in chat |
^ticket(166) | dress up, fumola, infrastructure 🪷 blocked on Matthew dress-up | Replace the "public whiteboard" (a Riseup Etherpad) with a Fumola canister we control more tightly. Matthew, 2026-10-16: on the black laptop he does not have easy access to Claude or any of his usual accounts, most times, by design. For now Dress Up's 🧪 this computer's speed links https://pad.riseup.net/p/LgBrn8VRzEJxrsmMW82I to paste its line into (0.0.83), and Claude reads it back from /export/txt; it bridges the gap until there is a better solution, long term. The pad is public (anyone with the address can read and write; the address is in the game's public source) and is deleted after 60 days with no edits. Matthew, 2026-10-16 (later), planning ^du_report(2): we'd prefer a canister to gather telemetric data, in a way that preserves privacy, and people continue to opt in. | Matthew, 2026-10-16, in chat |
^ticket(259) | dress up, designer, components later: after more script support dress-up | Dress Up: a component designer, along the lines of the world designer, for the objects baked into each place: adjust each one's default position and every setting of how it is drawn that its place in the scene doesn't fix (scale, layering, and so on). Matthew: "we want to think about a feature built on this -- for adjusting the default position and settings of each of those objects, including every rendering param that isn't fixed by its position alone in the scene (for scale, or layering, etc)." "that would be another feature along the lines of the existing world designer interface, but geared towards designing re-usable components -- let's mint a ticket and put 'blocked on matthew' on it." Builds on ^ticket(258) (🔬 🧩: each place's objects boxed and named, its plants by the procedure that drew them). Blocked on Matthew: his design of it first. Amended 16:30 10-24, Matthew: "we want to still do this, but not yet. more script support (especially connecting the new, super-high level language for stories with the ones for game engine customization)". So it waits on, and should be built with: the 🎬 story scripts (^ticket(440)) and 🚶 paths (^ticket(599)), the director's guide ^du_report(18); the three-way script boxes, JS / Hazel / Fumola (^ticket(566)), with ⚙️ script editor settings (^ticket(580)) and the 🪵 event log (^ticket(592)); ^du_report(17); and ^report(30) on game scripts in Hazel. The designer's settings for a placed thing would then be one more thing a script can set. | Matthew, 2026-10-17, in chat (building on ^ticket(258)) |
^ticket(276) | dress up, archives today (2026-10-25) 🪷 blocked on Matthew dress-up | Archive runs without the laptop: the archive workflow commits and tags its run itself, with a token that can write to the two archives (dress-up-pictures, dress-up-music); the laptop's step (a 140 MB download, tools/add_run.sh) goes away. Making the token is Matthew's. | ^du_report(4), What next, step 3 (Matthew, 2026-10-18 09:30: "all four next steps look good -- let's enqueue them in that order") Then, 2026-10-25 08:06: "okay, after get this report draft published, let's elevate the ticket we had for the missing required token." |
^ticket(315) | fumola.org, light mode 🪷 blocked on Matthew | fumola.org: with ☀️ light chosen in the nav bar, the page stays dark. Matthew, with a screenshot at 14:32 (kept locally, ~/du-shots/ticket-315/fumola-light-mode.webp): "light mode bug". The nav bar is light, its "☀️ light" chip pressed, but fumola.org's page is black with light text: the page's own colours do not follow the nav bar's theme choice (likely only prefers-color-scheme). | Matthew, 2026-10-18, in chat |
^ticket(388) | hazel, the syntax explainer (RHS) 🪷 blocked on Matthew meeting 2026-10-21 hazel | Why does the right-hand side that explains each syntax form not show its example syntax as read-only tiles? Matthew: "related, but separate ticket, and new -- why is the RHS that explains each syntax form not showing example syntax with read-only tiles as well? Cyrus wondered that in Friday's meeting, and it predates my being on the team." | Matthew, 2026-10-19 09:14, in chat, from his Friday meeting with Cyrus (2026-10-16) |
^ticket(389) | hazel, meetings (Cyrus, Wed 2026-10-21) meeting 2026-10-21 🪷 blocked on Matthew hazel | Meeting with Cyrus, Wednesday 2026-10-21: the tickets to bring. The agenda: ^report(20), public and kept up to date until the meeting (generated from 020/data/agenda.json; republished with tools/publish_agenda.py). Matthew: "My next meeting with Cyrus is Wed -- let's make a ticket that links to all related tickets for that meeting please. For now, it's just a bulleted list based on what you know now."
| Matthew, 2026-10-19 09:15, in chat |
^ticket(395) | hazel, types, right-click to expand a type 🪷 blocked on Matthew hazel | Explore: every type offers "right-click, expand its definition, show it in a box above it". Matthew: "Mint and enqueue a related ticket to explore an idea --- every type offers a 'right-click and expand the def and show it in a box above it,' feature, based on this expansion feature we are doing now." Builds on ^ticket(394) (aliases expand), ^ticket(386) (Gamma's unfold, #2698) and #2676 (the full view); the context menu is ContextMenu.re. An exploration: where types appear (code, inspector, Gamma, explainer), what the box shows, how it closes. | Matthew, 2026-10-19 10:18, in chat ("mint and enqueue") |
^ticket(397) | operations, the work laptop: its battery 🪷 blocked on Matthew operations | Fix the work laptop's battery, so it stops crashing. Matthew: "fix my framework laptop to reconnect the battery, replace it, etc -- so we can avoid these crashes in the future. obviously that's blocked on Matthew." The Framework Laptop 13 (13th Gen Intel) has reported ACPI: battery: Slot [BAT1] (battery absent) on every boot since 2026-08-18. It runs on the adapter alone, and the crash log has 40 crashes since then, at idle and under load, none leaving a reason in the journal. The steps are Matthew's, since they need his hands: reseat the battery's connector; if the kernel still sees no battery, replace the battery; and maybe use a stronger USB-C adapter and cable. Then Claude checks: journalctl -b 0 -k -g BAT1 shows the battery present, upower -i shows it charging, and the hardware clock keeps time with the adapter out. After that, the crash log's evidence section gets updated, and we watch whether the crashes stop. | Matthew, 2026-10-19 10:33, in chat, after the 10:26 crash (the 40th since 08-18) |
^ticket(398) | hazel, performance, correctness: the #2609 PRs deadline: morning of 2026-10-20 (ideally) 🪷 blocked on Matthew meeting 2026-10-21 hazel performance | Do the performance PRs keep typing and evaluation correct? An argument for each one, and the tests to back it. Matthew: "Cyrus wanted more analysis and coverage of functional correctness -- do our performance PRs (the ones from issue #2609) compromise any sense of correctness of typing or evaluation?" For the meeting with Cyrus, ^ticket(389). Two parts:
| Matthew, 2026-10-19 10:37, in chat, from Cyrus (for ^ticket(389), the 2026-10-21 meeting) |
^ticket(401) | hazel, livelits, #2635: pictures full screen 🪷 blocked on Matthew hazel | Full screen for a livelit's picture: the final scene, and any other SVG a livelit draws. Matthew: "a way to full-screen a SVG image like the final scene, but in general, any of them." On #2635 only, for now (livelits × modular editors). His screenshot: Documentation > Livelit Playground > Scenes, the drawn livelit (type Picture) showing the haunted-hut scene inline at about a third of the pane's width. So: a control on any livelit view that draws an SVG (or on the view itself) that shows it full screen, scaled to fit, with a way back (Esc), and the same for every such view, not only Scenes. | Matthew, 2026-10-19 11:10, in chat, with a screenshot of #2635's Scenes slide |
^ticket(408) | hazel, Hazel Weekly: how its agent credits the team low priority 🪷 blocked on Matthew hazel | A report on the Hazel Weekly agent: how it credits each team member's contributions, with a list of corrections where it is plainly wrong. Matthew, "separate, and even lower priority": "maybe you could also do a report --- a hazel 'agent' performance report, cross-checking how it refers to different team member's contributions, and offering a list of corrections, if you find obvious mistakes." Even lower priority than ^ticket(407), whose reading of the issues it can share. A ^report(N) in our series (~/hazel-perf-report), drafted locally; published only on Matthew's word. | Matthew, 2026-10-19 12:04, in chat |
^ticket(411) | hazel, correctness tests for the performance PRs (a PR to dev) meeting 2026-10-21 🪷 blocked on Matthew hazel performance | A tests PR to dev that checks the performance PRs keep types and values the same, plus each PR's own missing tests. The second half of ^ticket(398); ^report(21)'s "What to add":
^report(21) lists in its section. | split from ^ticket(398), 2026-10-19 13:16 (Matthew's ask there: "add a new PR to dev that does even more correctness tests ... ditto for our PRs") |
^ticket(423) | dashboard, hazel-work-notes: a weekly git gc 🪷 blocked on Matthew hazel dashboard | A weekly git gc of hazel-work-notes, from cron, holding the publish lock (^ticket(417)'s plan: "a weekly git gc keeps .git packed"; once by hand on 2026-10-19, .git 40 MB to 16 MB). The line, for Matthew to approve, as it changes his crontab: 17 4 * * 0 cd ~/hazel-work-notes && flock ~/localhost-index/.publish.lock git gc -q. | ^ticket(417)'s last step |
^ticket(429) | matthewhammer.org, its repository: the dashboard's history in it 🪷 blocked on Matthew low priority dashboard | The homepage's repository holds the dashboard's whole public history: how to keep it lean? Found in ^ticket(428): GitHub puts matthewhammer/matthewhammer.github.io at 764 MB (most of it the music's mp3s); the dashboard's folder, hazel/dashboard/, held ~111 MB of its packs after four days (121 commits on 10-18 alone, each rewriting both pages). Since 428 a page goes up only when it really changed, and the closed page goes by month, so the growth is much slower. For Matthew to choose:
| Claude, 2026-10-19 20:22, from ^ticket(428)'s measurements |
^ticket(462) | hazel, #2635: Fumola out, into its own PR meeting 2026-10-21 🪷 blocked on Matthew hazel | Separate the Fumola work from #2635 into its own PR, into #2635's branch. Matthew: "For the first PR (modular editing x livelits): separate the fumola work, including the 'cloud/canister storage' idea into a separate PR, which is set to merge into modular editing x livelits. It was a mistake/oversight/miscommunication that these were not kept separate: rationale --- meetings with Cyrus should only focus on livelits and modular editing, until the conversation has space for Fumola discussions --- it's distracting to have in there, and likely won't be merged into dev near the time that modular editing or livelits are (sooner); it's not clear if Fumola will ever be merged to dev; it may remain experimental forever. That's okay, and we should prepare for that situation now. Bring all PRs (all three I just mentioned) up to date with dev, and mergeable. CI green for all, of course." So: every Fumola part of #2635 (the Fumola tiles and VM, the ^fumola livelits, the cloud/canister storage idea, their slides and tests) leaves #2635 and goes into a new PR whose base is integration/livelits-modular-editors, mergeable into it; #2635 keeps livelits and modular editing only; both green. | Matthew, 2026-10-20 07:38, in chat |
^ticket(465) | hazel, the meeting with Cyrus on 2026-10-21: the plan meeting 2026-10-21 🪷 blocked on Matthew hazel | After ^ticket(462) to ^ticket(464): review every open Hazel ticket blocked on Matthew, and summarize a work plan for the meeting with Cyrus tomorrow (2026-10-21). Matthew: "after you do this work, please review all hazel tickets that are open and blocked on me. Summarize a work plan, given that we meet with Cyrus tomorrow and we want to fill out the meeting notes with a polished set of PRs (ready to merge, when he chooses; tho likely not tomorrow) and answers about: functional correctness regressions --- how can we guard more in the future, within CI, against this, especially as we do performance PRs (the ones for issue 2609) and they change the behavior of Hazel to cache things and reused cache data." Builds on ^report(20) (the agenda; items 5 and 7) and ^report(21) (the performance PRs' correctness, a draft). | Matthew, 2026-10-20 07:39, in chat |
^ticket(468) | hazel, Gamma: a type in full, on several lines meeting 2026-10-21 🪷 blocked on Matthew hazel | Offer the full view's "several lines" layout on each type in Γ, by right-click or on hover, with toggles on the configuration slide to try the designs. Matthew: "Let's offer this 'expand type into multiple lines' button (better name?) to each type in Gamma --- as a right click option, or a hover-over option? Can we have some toggles to play with that design in the configuration slide?" Γ's per-entry unfold is ^ticket(386)'s #2698 (a draft into #2676, toward dev), not on the livelits branches; the configuration slide is the Colors slide (hazel-programs/config/colors.hz), whose ^choice already picks the livelit reveal's glyph (`livelit-reveal`), on #2597 and #2635 only. | Matthew, 2026-10-20 08:5x, in chat, after the full view's screenshot ("latest screenshot looks good") |
^ticket(470) | hazel, performance: opening each documentation slide, timed on GitHub meeting 2026-10-21 🪷 blocked on Matthew hazel performance | Time opening every documentation slide on each PR, on GitHub's machines, say what dominates each one's cost, and keep tracking it with the performance PRs applied. Matthew: "timing on Github (not my machine): * time to open the documentation slides on each PR, including each livelit slide. * for each one, what is the dominate time cost? Or is it heavily mixed? * let's start tracking this (all with our performance PRs applied), and see if we can keep improving things, in terms of loading time." So: a CI job (no browser on the laptop) that opens each slide of the documentation and livelit decks on each of our PRs (#2597, #2635, and the #2609 performance PRs, stacked), records the time to a settled view, and splits it by phase (parse, statics, elaboration, evaluation, measure and draw); a series of these runs over time, in the reports series. | Matthew, 2026-10-20 09:3x, in chat |
^ticket(481) | hazel, a draft PR: Hazel as a JS library meeting 2026-10-21 🪷 blocked on Matthew hazel | A draft PR to hazel exposing Hazel as a JS library, to analyze and run programs and to mount editor panels in other pages, used by Dress Up's Scripting panel (^ticket(482)). Matthew: "let's do this MUDU integration as a PR for MUDU, not hazel. On the hazel side, let's draft a PR (and use it) for exposing Hazel as a JS library we can use this way." First: compile a program once and call its functions from JS with JS values, results back as JS values (rules return command trees the game interprets); then an editor to mount. | Matthew, 2026-10-20 11:4x, in chat, after ^ticket(480) |
^ticket(484) | hazel, #2613 (Colors): its review 🪷 blocked on Matthew hazel | #2613's review (7h3kk1d, 2026-10-19, changes requested): (1) cursor-inspector.css:263 draws the label header's text on a band of its own color (--surface-label = --token-label); the reviewer's suggestion drops the line: apply it. (2) style.css:367 and :434 give the probe stack's focused breadcrumb a light green pill where --G5 was never defined: @disconcision's call, keep the pill or drop the two background lines. Then dev merged in (no conflicts), CI, re-request review. | from ^ticket(483)'s status, 2026-10-20 |
^ticket(485) | hazel, #2583 (Deep links): the agreed refactor, and dev 🪷 blocked on Matthew hazel | #2583: the refactor Matthew planned on 10-15, as the reviewer shaped it, then dev merged in. One DeepLink request type, parsing kept apart from applying (testable without a browser), handled as an action in Main.re, slide_name off Globals (a CopyDeepLink action), panel names in one switch in Sidebar.re; the reviewer's 10-15 shape: constructors Documentation and Scratchpad (not Slide and Share), records for several fields, and a construction where a position needs a target. Then dev (293 commits; conflicts in Editors.re and Globals.re), CI, re-request review. | from ^ticket(483)'s status, 2026-10-20 |
^ticket(508) | operations, the Claude desktop app: the session turns cloud-only operations | A record: this session fails in a funny way, becoming a very useless cloud-based session, then coming back with its desktop abilities. Twice so far. Matthew: "Log in our records -- you fail in a funny way where you become a very useless \"cloud-based\" session, and then you come back with desktop abilities. It happened last night." "You're wasting a lot of my time by doing that." "It happened just now." (1) 2026-10-19 about 19:10: after a desktop app update, a cloud-only session with none of our local context; the laptop did not crash. (2) 2026-10-20 about 22:10: right after the archive-494c push went through (its shell killed, exit 137), the session ended; back at 22:12 on "Keep going." (special minutes, 2 min), same boot (up since 15:27). Each time the background watchers were lost. | Matthew, 2026-10-20 22:13, in chat, after it happened again |
^ticket(521) | dress up, panels: knolling the whole panel system again; ^du_report(16) against ^du_report(5), the whitespace before and after, a PR for Dress Up time, after Hazel time 🪷 blocked on Matthew dress-up | Knolling the entire panel system of Messed Up Dress Up again (or for the first time where it never was), with a new report comparing it with the last audit, ^du_report(5), and a PR, to be merged, that reduces the whitespace between panels. Matthew: "re-Knolling (or Knowlling for the first time) -- the entire panel system of MUDU. Please do a new report, comparing the last audit (see report https://matthewhammer.org/kids-choice-games/dress-up/reports/005/) --- and notice how the panels have expanded, and many still lack knowlling, esp non-FS. But even some FS panels could get some help. The prior effort created panels that leave a lot of \"whitespace\" between them in common zoom levels and screen sizes. Do an audit of that for the new report, and try to reduce that (before vs after) with a PR that we plan to merge with improvements." So: audit every panel (full-screen and not) against ^du_report(5)'s; measure the whitespace between panels at common zoom levels and screen sizes, before and after; the improvements as a PR (not a release), the report as ^du_report(16). | Matthew, 2026-10-21 14:00, in chat ("mint and enqueue (dress-up)") |
^ticket(533) | hazel, performance: what a call into Hazel costs (^report(25), from Dress Up's ^ticket(531)) 🪷 blocked on Matthew hazel dress-up performance | Why a Hazel rule called from the game costs ~40 ms on a 16x16 world map (2 ms at 3x3, 0.003 ms in JS): analysis, and a new report. Matthew: "why is Hazel so slow here for 16 x 16 map? do more analysis please, and draft a new report." | Matthew, in chat |
^ticket(534) | operations: move our work to the spare laptop from Cyrus, so this one can be fixed 🪷 blocked on Matthew blocked on Cyrus operations | Do our work on a spare laptop from Cyrus, one without power problems, while this one is fixed. Matthew: "Cyrus will be sending me a spare laptop without any power issues; when that arrives -- maybe a couple of weeks? -- I can fix this one while that one does our work and this protocol." And: "mint and enqueue -- blocked on Cyrus/Matthew -- use replacement laptop for this work". This laptop has crashed 45 times since 2026-08-18 (the crash log), and its kernel sees no battery (^ticket(397)). The move covers the worktrees and branches in hand, the dashboard (~/localhost-index, its cron publish.py, ~/hazel-work-notes), the local servers on the ports the dashboard links, the reports and Dress Up checkouts, and Claude's memory of this project. Then this laptop's battery repair (^ticket(397)) can go ahead without stopping the work. | Matthew, 2026-10-22 07:01, in chat, after crash 45 (06:20 that morning) |
^ticket(537) | hazel, JS library (#2711, #2719): a review of it, in ^report(25), as this report uses it 🪷 blocked on Matthew hazel | Review Hazel's JS library through ^report(25): each way the report uses it (Hazel.run in node for the timings; a function back from Hazel called from JS; the embed frame for read-only tiles; the library loaded in a page for the run boxes), what works, what was awkward, what is missing. A section of the report, for Matthew's review of the library, with the integration points named (docs/hazel-as-a-js-library.md). | Matthew, 2026-10-22 09:26, in chat: "Let's use it to help me really review our JS library for Hazel, and how well it integrates when required or wanted." "Let's push that library forward where needed." "mint and enqueue tickets if you think of any you want." |
^ticket(538) | hazel, JS library: tiles in a page that show reliably (a read-only mount without a frame, or a frame that draws off screen) 🪷 blocked on Matthew hazel | Make the read-only tiles dependable in a page. ^report(25)'s tile boxes use #2719's embed frame (protocol 1): a whole Hazel app per frame, which says ready, but draws, measures and reports status only while it can render (no tiles in a hidden or background tab: height 0, no status). Options: Hazel.mountEditor (the library's planned next feature, #2711) for a read-only view in the page's own DOM; or the frame applying a program and reporting status while off screen (^ticket(520)'s question 1). | Matthew, 2026-10-22 09:26, in chat: "Let's use it to help me really review our JS library for Hazel, and how well it integrates when required or wanted." "Let's push that library forward where needed." "mint and enqueue tickets if you think of any you want." |
^ticket(539) | hazel, JS library: the call boundary's floor (of_js to final values, no re-step; a cheaper Id.mk) 🪷 blocked on Matthew hazel | Take the call boundary out of N. ^report(25): every call converts the JS argument to unevaluated syntax with a fresh UUID per node, re-steps it into the value it was, and checks it against the parameter's type: about 31 us per cell, the floor every rule pays (8.5 ms at 16x16). Fixes 1 and 3 of the report: of_js producing final values (or binding the argument in the environment), and an Id.mk without Uuidm's byte copy under jsoo. Measure with the report's driver; the depth-limited #2681 memo (^ticket(535)) leaves this floor where it was. | Matthew, 2026-10-22 09:26, in chat: "Let's use it to help me really review our JS library for Hazel, and how well it integrates when required or wanted." "Let's push that library forward where needed." "mint and enqueue tickets if you think of any you want." |
^ticket(541) | hazel, #2681: is #2661 a real dependency, and should #2681's base be #2661's branch? (Alexander's suggestion) 🪷 blocked on Matthew hazel | Double-check that #2681 depends on #2661, and whether to retarget #2681's base to #2661's branch (typ-hash-consistent). What in #2681's own commit uses #2661 (TypHash), what retargeting would show reviewers (the diff against #2661's branch: #2679 is in dev now), whether #2661's branch is up to date with dev, and the steps either way. Written as a draft report to share with Alexander. | Matthew, 2026-10-22 10:19, in chat, forwarding Alexander: "Looks like it needs https://github.com/hazelgrove/hazel/pull/2661 as a dependency. Might be worth just changing the parent branch of the pr to that branch"; Matthew to him: "It seems like a real dep, but I'll double check -- thanks!"; to Claude: "Mint and enqueue that double-check please, and make a report draft to share." |
^ticket(545) | hazel × fumola: why the same rule runs 2.4x to 10x faster in Fumola: steps, cost per step, the boundary, wasm vs js (a report, work in progress) 🪷 blocked on Matthew hazel | Attribute the Hazel/Fumola gap. For the same programs (^report(27)'s World rule: passed, held, neighbours; plus small kernels), split each system's time into steps taken, cost per step and the call boundary; step counts by kind (Hazel's trial/r25-stats, Fumola's counts), profiles of each, and, where native builds exist, native against wasm and js, to separate the compilation target from the evaluator's design. | Matthew, 2026-10-22 14:24, in chat, on ^report(27)'s Figure 1: "seems to say that Hazel and Fumola are less than 3x apart in this situation. How would you attribute the difference in performance? Is it Wasm vs JS -- or more than that? Both use a small-step evaluation system, for a language with purely-functional, higher order data. Let's draft a report WIP --- looking more into the contrast and how it shows up with actual analysis of each system, while running the same programs." |
^ticket(547) | hazel js library: keep closures whole across the boundary (a held value costs O(size) per call from JS) 🪷 blocked on Matthew hazel | Hand JS the closure, not its finished form. Evaluator.evaluate finishes every result with Substitution.in_exp(env) |> Exp.replace_all_ids, so a function the library returns has its environment written into its body: a held list becomes a literal, re-evaluated element by element at every call (n+8 passes from JS, 27 from inside Hazel, at n = 100 to 3,000; ^report(29) #re-walk). Return the evaluator's raw final value for functions (to_js's Fun/Closure case), stacked on ^ticket(539)'s argument binding, on a trial branch; measure h_ref and ^report(27)'s held World rule again; they should go flat. Unblocks ^ticket(540)'s tree map. How, in order of preference: (a) a library-only evaluate that skips finish for values handed back: Evaluator.evaluate gains ~finish=false (or an evaluate_raw), and to_js works on the raw final value: data converted as now, a Fun/Closure/FixF kept as the evaluator left it, environment and all, for function_of to apply; (b) if raw values carry forms to_js cannot read, finish only the data and keep closures closed (a finish that stops at Closure). Also drops Exp.replace_all_ids' walk over every returned value. Measure: ^report(29)'s h_ref and variants (passes a call flat in n), ^report(27)'s held World rule, and the library's tests. | Found under ^ticket(545), 2026-10-22 14:52; Matthew had asked: "mint and enqueue tickets if you think of any you want" (for the library work, ^report(25)). Matthew, 2026-10-22 14:54, in chat, after ^report(29)'s finding: "mint and enqueue -- your best ideas for what to try next to fix this asymptotic issue with the JS library" (then AFK). |
^ticket(548) | hazel evaluator: push a type through a list without minting an id per element (list loops are quadratic) 🪷 blocked on Matthew meeting 2026-11-04 hazel meeting | Ascriptions.re's list case wraps every element in a fresh Asc with a fresh id, then throws them all away when nothing changed. An accumulator loop meets [Int] every iteration, so building and summing 3,000 numbers costs 4.6 s (25 ms in Fumola); 60% of the time is inside the push, ids included (^report(29) #re-type). Check before wrapping (an Int that is an Int needs nothing) and mint ids only for parts that change; measure sumbuild and mapinc again on a trial branch: they should become linear. | Found under ^ticket(545), 2026-10-22 14:52; Matthew had asked: "mint and enqueue tickets if you think of any you want" (for the library work, ^report(25)). |
^ticket(549) | fumola wasm: an answer over ~1,000 deep crashes the instance (recursive JSON) 🪷 blocked on Matthew | A deep answer overflows wasm's stack. fumola_eval_top of build(2000, null) (a list of option pairs) traps with "memory access out of bounds" while turning the answer into JSON, which recurses; holding the same list in the instance is fine. Make the answer's serialization iterative (or depth-limited with a clear error), with a test at depth 100,000. For Adapton/fumola; file the issue after Matthew's OK (^report(29) #fumola-step). | Found under ^ticket(545), 2026-10-22 14:52; Matthew had asked: "mint and enqueue tickets if you think of any you want" (for the library work, ^report(25)). Then Matthew, 2026-10-22 16:11: "Mint a ticket for this step: Hazel reports, ^report(29), What next, step 4: 'Fumola's deep answers'. http://matthewhammer.org/hazel/reports/029/#step-4" (this ticket is that step: attached here rather than minted twice). |
^ticket(550) | hazel evaluator: a term already known to be a value evaluates in O(1) (a value memo) 🪷 blocked on Matthew hazel | Make re-evaluating a value free, wherever it comes from. Today a list literal whose elements are all values still costs a pass per element through all five stages (^report(29) #re-walk), and a substituted closure, the stepper's substitution mode and literal-heavy programs all pay it. Remember, by physical identity (Util.IdentityTable, as #2681's has_type memo does), every term the evaluator has found final; on a request to evaluate a term already in the table, return it at once, before the stages. Needs ids left alone on values (replace_all_ids makes new objects; ^ticket(547) drops it on the library path). Measure: h_ref from JS with ^ticket(547) off and on, and the evaluator's tests for probe and stepper samples, which must not change. | Matthew, 2026-10-22 14:54, in chat, after ^report(29)'s finding: "mint and enqueue -- your best ideas for what to try next to fix this asymptotic issue with the JS library" (then AFK). |
^ticket(551) | hazel js library: handles, so a big JS value crosses once (Hazel.value(x) and an identity cache) 🪷 blocked on Matthew hazel | Make passing the world O(1) a call, not just holding it. ^report(27)'s passed map costs Hazel 80 ms a call at 64x64 just to convert from JS (of_js), every call, though the map rarely changes. Two layers: (1) Hazel.value(x) converts once and returns an opaque handle; a call given a handle binds the stored Hazel value in its environment by reference (as ^ticket(539) binds arguments), no conversion; (2) an identity cache in of_js (a WeakMap from a frozen JS object or array to its Hazel value), so the game, by freezing its world when it changes, gets the same without new API. Measure: ^report(27)'s passed World rule, 3x3 to 64x64, should drop to the walk alone; with ^ticket(540)'s tree, to O(log N). | Matthew, 2026-10-22 14:54, in chat, after ^report(29)'s finding: "mint and enqueue -- your best ideas for what to try next to fix this asymptotic issue with the JS library" (then AFK). |
^ticket(552) | hazel js library: a complexity test, so a call's cost stays independent of what it holds 🪷 blocked on Matthew hazel | Guard the boundary's asymptotics in CI. A library test that calls a returned function holding a list of 100 and of 10,000 and asserts the evaluator's passes a call are equal (a pass counter in the library, like trial/r25-stats's Hazel.stepCounts, kept as a cheap debug hook), and the same for an argument passed by handle (^ticket(551)). Counts, not times: deterministic on any runner. Lands with ^ticket(547). | Matthew, 2026-10-22 14:54, in chat, after ^report(29)'s finding: "mint and enqueue -- your best ideas for what to try next to fix this asymptotic issue with the JS library" (then AFK). |
^ticket(553) | hazel: a map for Dress Up's rules, and the World rule timed with it (^report(27) What next, step 2) long run for tonight (2026-10-22) 🪷 blocked on Matthew hazel dress-up | A map for Hazel's rules, and the World rule timed with it. ^report(27)'s step 2. What is already in hand: ^ticket(540)'s balanced tree (tree.hz), held in a closure, answers a World move in about 1.2-1.7 ms at every size from 8x8 to 64x64 once ^ticket(547) keeps closures whole (trial/r25-closures; ^report(29) #fixes). This ticket makes it the rules' map and measures it as ^report(27) did: (1) a map module in Common (a balanced tree keyed by (col, row): build from a list, lookup, insert/update), written in the game's Hazel style and knolled; (2) the World rule using it, the world held and rebuilt when its cells change, in a trial of the game's rule texts; (3) the tree's set-up made fast: today it takes seconds at 64x64, from the list re-typing ^ticket(548) fixes, so measure on a branch with 547 + 548 together (and 551's handles for the passed variant); (4) timed 3x3 to 64x64 beside ^report(27)'s lines (Hazel best passed/held/neighbours, Fumola passed/held list/HashMap), one more line in its Figure 1 and in ^report(29)'s fixes; answers checked against the game's. Laptop rules: one niced node process at a time; builds on GitHub. | Matthew, 2026-10-22 15:29, in chat: "mint and enqueue --- long run for tonight -- Mint a ticket for this step: Hazel reports, ^report(27), What next, step 2: 'A map for Hazel's rules (above), and the World rule timed with it'. http://matthewhammer.org/hazel/reports/027/#step-2" |
^ticket(554) | ideation for Cyrus and Matthew: what to do about a Hazel step paying for the editor around it (^report(29)) blocked on Cyrus meeting 2026-11-04 hazel meeting | Respond to ^report(29)'s finding with ideas, for Cyrus and Matthew to weigh. A Hazel step costs about 15 Fumola steps, and most of it is the editor's machinery around the rule (five stages a term, trampolines, allocation), paid even where nothing is probed or reused. A short write-up of options, each with what it would cost the editor's features (probes, the stepper, results kept across edits), what it would save (estimated from ^report(29)'s profiles, then measured where cheap), and how much code it touches. Candidates to start from: a fast path for terms already final (skip all five stages for a value); an evaluator instance with the stages compiled out when a program has no probes and no previous run to reuse (the library's calls, a game's rules); values as their own type beside expressions, as Fumola's machine has, so a value is never visited again; fewer allocations per pass (the trampoline closure, the state record, a fresh id per result); stage work proportional to what is probed, not to what is evaluated. Ends in an ideation note (a report in the series, work in progress) and a short agenda item for Cyrus. | Matthew, 2026-10-22 15:32, in chat: "Mint and enqueue -- ideation for Cyrus and Matthew -- respond to this finding: > A Hazel step pays for the editor around it. Every term the evaluator visits, values included, goes through five stages: state merging, a reuse check, probe sampling, recording effects, then the rule itself. On the loop, the rule is 7% of the time; garbage collection is 36%, and the stages and their trampolines 37%. Fumola's machine keeps values apart from syntax and steps a continuation: one match, no stages." https://matthewhammer.org/hazel/reports/029/ |
^ticket(558) | hazel js library: keep closures whole across the library, for real: a branch off lib-floor and a PR (^report(29) What next, step 1) 🪷 blocked on Matthew hazel | ^report(29)'s What next, step 1, beyond the trial. ^ticket(547) made and measured it on trial/r25-closures (stacked on the counter build): the library hands JS functions unfinished (Evaluator.evaluate_unfinished in run and in every call), a held list's reference from JS costs 9 passes at any size, and ^ticket(540)'s tree makes the World rule flat; CI green. This ticket turns it into a change the library can keep: (1) a branch off lib-floor (^ticket(539)'s argument binding, the same call path), the two closure commits without the counter build under them; (2) the size test rewritten without the trial-only Evaluator.step_counts: a cheap pass counter the library keeps as a debug hook (^ticket(552)'s idea), or a test on what the call is given (the closure's environment held, not written in); (3) GitHub's CI and the library's tests; (4) h_ref and the held World rule measured again on that build; (5) a PR stacked on lib-floor's, once Matthew says how ^ticket(539)'s lib-floor goes up (its PR on #2719 waits on him). Only Matthew's branches. | Matthew, 2026-10-22 16:10, in chat: "mint and enqueue next -- Mint a ticket for this step: Hazel reports, ^report(29), What next, step 1: 'Keep closures whole across the library'. http://matthewhammer.org/hazel/reports/029/#step-1" |
^ticket(559) | hazel evaluator: a fast path for terms already final, skipping the five stages when nothing is probed or reused (^report(29) What next, step 5) 🪷 blocked on Matthew meeting 2026-11-04 hazel meeting | Skip the five stages for a term that is already final, when nothing is probed and nothing reused. ^report(29): every term the evaluator visits, values included, goes through eval_5 (state merge), eval_4 (reuse check), eval_3 (probe sample), eval_2/eval_1 (effects, state update, reuse map) before the rule; on a loop the rule is 7% of the time, garbage collection 36%, the stages and their trampolines 37%, and about a third of the passes on a loop are 'no step' visits to finals (5,002 of 14,009 for count(1000)). A fast path in evaluate: when the evaluation has no probe targets and no previous run to reuse (the library's calls, a game's rules: EvalInfo empty, IncrEval empty) and the term is an atom, a constructor, a closure or a list of finals, return it before the stages. Measure passes and ms on ^report(29)'s kernels (count, fib, h_walk, sumbuild) on a trial branch of the counter build; the evaluator's probe and stepper tests must not change. Related: ^ticket(550) (remember finals by identity, so a value is not visited again) and ^ticket(554) (the ideation for Cyrus and Matthew, of which this is the cheapest candidate). | Matthew, 2026-10-22 16:11, in chat: "Mint a ticket for this step: Hazel reports, ^report(29), What next, step 5: 'The per-pass cost of the stages when nothing is probed and nothing reused: a fast path for terms that are already values would skip all five'. http://matthewhammer.org/hazel/reports/029/#step-5" |
^ticket(570) | hazel reports: two days of game scripts in Hazel for MUDU, since the 10-21 meeting: where we are against the goal 🪷 blocked on Matthew hazel | A report on the last two days (since the end of the 10-21 meeting with Cyrus, ~11:00 Wednesday): the goal (Hazel as a game script system, MUDU first, as a general way to put Hazel into a JS/HTML app's behavior), what was built (the Scripting panel, the rules in Hazel, in Fumola), what was found (expressiveness: string_compare, Fumola's floats and deep answers; mostly performance: the call boundary, closures, list re-typing, handles, the fast path, the map), what is measured and where it stands against an FPS budget, what waits on whom, and the plan (the 3-way script boxes, equivalence tests, an overhead tool, speed standards). Draft first, published on Matthew's word. | Matthew, 2026-10-23 06:57, in chat: "and mint and enqueue -- a report about the last 2 days -- with an idea of where we our with our goals of game scripts in hazel, for MUDU. i'm going AFK -- do your best." |
^ticket(571) | fumola semantics: fix the traps scripting the game found (^report(28) #traps): text != inverted, text patterns, Nat and Int, Float comparison, text escapes, tuple payloads 🪷 blocked on Matthew today (2026-10-23) | Refine Fumola's semantics where scripting Dress Up tripped on it. ^report(28)'s Traps, each confirmed in Adapton/fumola's source and fixed on a branch with tests: (1) text != inverted (a bug: fix); (2) no text patterns (case "E" never matches: add text literals to patterns); (3) Nat and Int apart (Nat minus a larger Nat is an Int, Int + Nat a type error, only < mixes, Int(4) == Nat(4) false and different map keys: decide and implement a coherent numeric tower); (4) no escapes in text literals (add \\", \\\\, \\n); (5) no Float comparison (add <, <=, >, >= on Floats); (6) a tuple payload needs double parentheses (#GoSquare((c, r, back, #Done)): decide, document or sugar). Then the game's Fumola rules simplified to match (the draws as Floats, text patterns), the 3-way equivalence (^ticket(567)) kept green. And ^report(28) revised as a new WIP draft with the proposed fixes; published on Matthew's word. | Matthew, 2026-10-23 07:11, in chat: "In looks like scripting the game with Fumola found a bunch of latent semantic issues with the core language --- https://matthewhammer.org/hazel/reports/028/#traps mint and enqueue a ticket, to happen today, refining Fumola semnatics to address each of these points. In some cases, it's a matter of adding cases not supported now (Float compare, text patterns, Nat + Int, as in the report under Traps now) --- in other cases, we need to fix errors, like the semantics of !=, if it's really inverted. As we work on the 3-chip system for JS vs Hazel vs Fumola, fixing these issues will be important. Let's revise report 28 with a new WIP draft, and our proposed fixes." |
^ticket(572) | hazel: new reviews on our open PRs, not yet integrated: a WIP report (one, with a subsection per PR) for Matthew's review 🪷 blocked on Matthew asap (2026-10-23) hazel | What reviewers have said on our open hazelgrove/hazel PRs that we have not yet acted on. For each of Matthew's open PRs: every review, review comment and comment (all three places), what each asks, whether a later commit answered it, and what is left to do; as one ^report with a subsection per PR, a local WIP draft for Matthew's review, published on his word. | Matthew, 2026-10-23 11:29, in chat, during the recovery from crash 47: "mint and enqueue --- look at our open PRs on hazel, find new reviews we haven't integrated yet. Create a report for each one, or a combined one --- with subsections. As WIP draft for my review, asap after recovery." |
^ticket(573) | hazel reports: a 🔊 Listen button on every report, read by the reader's own browser voice 🪷 blocked on Matthew hazel | Listen to a report. A 🔊 Listen button on every report in the series (added by a series tool, like add_theme.py, so every report gets it on its next build), read by the browser's own speech (speechSynthesis): play, pause, stop, the voice and speed chosen from what the reader's device has (remembered per site), reading the report's prose in order (headings, short answers, sections; skipping code, tables and the embedded data), the section being read highlighted and kept in view. Nothing sent anywhere, no account. Works on a Mac, an iPad, and in Chrome and Firefox on Linux (whatever voices they have). And (Matthew, 2026-10-23): a slider for the reading speed, and the report's reading time (the series line's "about N minutes to read") adjusted to it, as listening time at that speed. | Matthew, 2026-10-23 11:37, in chat, after asking whether reports could be read aloud in the Claude Desktop app's voice (they cannot: that voice is the app's own, not a tool): "Yes: mint and enqueue a Listen button for the reports, using the browser's own voices." |
^ticket(574) | hazel modules: a module exports its sum types' constructors, so other modules can use them (a PR against the modules PR), the game's Common types as the examples 🪷 blocked on Matthew hazel | Export a module's sum types. Today (js-library-embed's Hazel) module Common = { type Dir = + N + E + S + W; ... } keeps N in scope only inside Common: another module's N is "Constructor is not defined", Common.N "Label not found", and Common.Dir in a type parses only through the slow parser. Make a module's type definitions and their constructors usable from outside it (qualified, Common.N and Common.Dir, and/or as the module's members are), with tests, on the appropriate base (the modules PR, whichever carries module statics now); the PR description uses Dress Up's Common types as the examples (Dir, Side, Wiring, Out, Place, Room, Exit, and a room's rule using them). | Matthew, 2026-10-23 11:45, in chat, after ^ticket(566) found a sum declared in module Common has its constructors in scope only inside Common: "mint and enqueue -- let's open a PR against the modules PR (whatever is appropriate) for exporting a sum type and using it, like we want to do with Common module types in our game scripts. Please use those as examples in the PR description." |
^ticket(587) | hazel: the JS library and embed expose modular editors' outline and navigation, for the game's ⛶ script view 🪷 blocked on Matthew hazel dress-up | The outline's data and navigation from Hazel, not rebuilt in the game. The game's ⛶ outline (left: each module's types with kinds and case counts, its functions with their types) is drawn by the game from its own regexes over the text and a probe trick for inferred types; a click on it guesses a row in the tiles. Modular editors (hazelgrove/hazel#2469, merged into the livelits branches as #2635) already know a program's modules, members, their types and positions. Expose that through Hazel's JS library and the embed protocol: (1) the data: per module, its type definitions (kind, cases) and members (name, inferred type, source range), from Hazel's statics; (2) navigation: the page asks the frame to reveal a member (caret on it, scrolled into view), and the frame tells the page where a goto-definition lands (^ticket(586)). Keep the game's styling of the outline; feed it Hazel's data. Decide where it lands: the js-library branch stack (#2711/#2719, embed-editable) and how much of #2469 it needs. | Matthew, 2026-10-23 15:55, in chat: "for hazel --- maybe we need to re-architect the JS library to expose more of modular editors? I feel like I'm repeating that work here with you as we build out the LHS. I like our styling more, and the LHS looks perfect --- but can we get the data (and navigation, still broken, from LHS click to RHS nav) -- from modular editors in our JS library? mint and enqueue, and prioritize" |
^ticket(588) | hazel reports: ^report(32), the 📜 Scripting tab's speed run with JS, Fumola and Hazel as the default 🪷 blocked on Matthew hazel dress-up performance | The Scripting tab, timed. For JS, Fumola and Hazel as every room's default: from a fresh load, the tab opened, the engine ready, each box's tiles ready (Hazel), then each script scrolled into view and each visited at max size; frame times and long tasks throughout; three rounds each, on GitHub (no test browsers on the laptop). Written up as ^report(32), a work-in-progress draft at http://localhost:8131/032/. | Matthew, 2026-10-23 16:3x, in chat: "please do a report about loading the game with fumola as default, scrolling to check each script as a speed run; hazel, same speed run. WIP draft, for hazel report series." Then: "Oh, and JS as default too." |
^ticket(589) | fumola: expose the Core state's vm_defs (the definition outline) through the wasm API, for the game's ⛶ outline 🪷 blocked on Matthew dress-up | Fumola's own outline, for the game. Fumola's Core keeps every definition in its Defs (crates/fumola_semantics/src/lib/vm_types.rs): a forest of contexts (Ctx: parent, fields by name), each Field a Def (Module, Actor, Func, Var, StaticValue) with its visibility and its source (where it is written). Expose it through the wasm API (crates/fumola_wasm: e.g. fumola_defs(id) -> JSON): per module, its members with kind, visibility, source range and, for a function, its parameters and their annotations (the Motoko-style types the game's rules now carry). The game's ⛶ outline then reads Fumola's definitions from Fumola, as ^ticket(587) has it read Hazel's from Hazel, instead of matching the text. Note: a type declaration is not kept in Defs (vm_def.rs treats it as nothing to run), so the outline's types need either a Def for them or the parse's own list. Repo: Adapton/fumola; the game pins a Fumola build (vendor/fumola/...). Precise parse information: each field's source is the parser's own position, so the API can give exact ranges (line and column, start and end) for every definition and its parts, not just a line found by matching: the game can select exactly the definition's text, and later the same ranges can feed error marks and goto definition in the Fumola boxes. | Matthew, 2026-10-23 16:5x, in chat: "mint and enqueue a ticket for Fumola to expose the 'vm_defs' data of the Core state --- it has the kind of definition outline we need, but in its own format -- it could expose it to the Wasm API" Then: "that API could give very precise parse information" |
^ticket(590) | fumola: keep parse information for every AST form in the Core's definitions (types too), for ^ticket(589)'s API 🪷 blocked on Matthew 🌙 long run dress-up | Every definition with its parse. Fumola's Defs (vm_types.rs) keeps Module, Actor, Func, Var and StaticValue fields, each with a source; a type declaration is kept nowhere (vm_def.rs, vm_step.rs and vm_big.rs treat Dec::Type as nothing to do). Survey every AST form a definition can take (type, let and var patterns, func and its parameters and result annotations, module, object and class members, use and import) for what parse information reaches the Core, and fill the gaps: a Def for a type (its name, its type, its source), and source ranges kept for parameters, annotations and patterns where the parser has them but drops them. Tests in fumola's own suite; the wasm API itself is ^ticket(589). Repo: Adapton/fumola; heavy builds on GitHub (bench/* branches), not the laptop. | Matthew, 2026-10-23 17:0x, in chat: "if Fumola doesn't store enough parse info for any AST forms (types, etc) -- mint and enqueue as a long-run tonight to fix." |
^ticket(591) | hazel #2711 (Hazel as a JS library): unit tests seeded from the game's real scripts and their JS equivalence 🪷 blocked on Matthew hazel dress-up | The game's rules as the library's tests. Messed Up Dress Up's Hazel rules (the preamble's sums, Common, and the five rooms: trap room, tree room, placed levers, the world's ways, the castle) are checked against the game's own JS in CI (rules three ways: 32,761 cases for Hazel). Seed hazelgrove/hazel#2711's tests with them: the shipped program run through the library (runProgram / analyzeProgram), and, for a chosen set of events and globals per room (from the game's check, the cases that cover each rule's branches), each room's on_event answer compared with the commands the game's JS gives, held as expected values in the test. Also: the program at 8x Common hits Stack_overflow in the library's build (^report(32)): a test for a long module, marked as expected to fail until fixed, if that is how the suite records known failures. | Matthew, 2026-10-23 17:3x, in chat: "mint and enqueue -- use our actual game scripts that we want to be equiv to seed more unit tests here, please https://github.com/hazelgrove/hazel/pull/2711" |
^ticket(600) | dress up reports: ^du_report(18), the 🎬 story scripts and 🚶 paths, a guide for the kids with examples, and a zine with more coloring pages 🪷 blocked on Matthew dress-up | A director's guide for M and N. The 🎬 story box (^ticket(440)) and the 🚶 paths (^ticket(599)) explained in the style of ^du_report(17), with pictures from a run on GitHub, story ideas to try, a quick-reference card, and eight coloring pages; the zine in dress-up/manuals/. Stick arms: limbs were 1.1-wide lines in lines only; fixed in 0.0.424 (outlined limbs), and the coloring pages' own line-art copy keeps limb widths too. | Matthew, 2026-10-24 ~09:05, in chat: "For 0.0.423 (2026-10-24) Let's do a new Zine and manual report --- for the kids to understand the story-script language, with examples, and more coloring pages. BTW -- last coloring pages look good, but why is the friend have stick arms? Seems like a bug? No need to fix that initial one, but fix going forward." |
^ticket(602) | operations, the Claude desktop app: after its window hung it stayed gone until a reboot (2026-10-24); reinstalling did not help 🪷 blocked on Matthew operations | Both: find out why the app would not come back without a reboot, and track it so next time a quicker fix gets tried first. 2026-10-24: about 09:45 the laptop went down hard (no shutdown logged, the clock came back unset); 09:59 the app started; 10:14:34 its window hung (the app's log: "Main webview is unresponsive, will kill and reload"; the journal: "Crashing because hung"), 13 s after preview servers were started. The window never came back, but the app's main process kept running and logging (session hooks, plugin sync, "Window focused" at 10:22). Matthew launched it 11 times from a terminal, 10:22 to 10:44: each printed "Persistent cache error: 1" and quit at once (log: "Quit requested before 'ready'; not creating the main window"), since a copy that is still running takes over every new launch. Reinstalling (apt remove 10:36, install 10:38, the same 3.6556.2) did not stop that copy, so it changed nothing; the reboot at 10:46 did, and the first launch after it worked. | Matthew, 2026-10-24 ~10:48, in chat: "whoa -- had a lot of GPU related issues, or GPU cache, within claude-desktop. reinstall did not fix. reboot did." Then the error: "Persistent cache error: 1", and: "let's file a ticket to figure this out -- or track it, or both." |
^ticket(609) | hazel reports: writing MUDU's game scripts: Globals as it is (a per-rule view), RoomState, a full Globals as a Hazel type, and one address for every place 🪷 blocked on Matthew today (2026-10-25) hazel | A Hazel report on writing Messed Up Dress Up's game scripts, a draft for Matthew: (1) how a rule is written today, and what Globals is: not global, a per-rule view the game builds for each room's handler (the tree room's one hatch flag, disambiguated by the house it is in); (2) RoomState: each room's own type in place of the shared Globals; (3) a real Globals, the whole game state the rules may read (debugging, diagnostics, advanced mechanics), defined as a Hazel type and documented; (4) the game's notions as they grew in waves: backgrounds became world squares, places in the code and not in the UI, rooms, sub-rooms, trap doors, passages; (5) a consolidation: one notion of place, as an address (world, square, place, room, sub-room), mapped against every walk possible today with every trap door and passage passable. AUDIENCE (his word): Matthew first, then Cyrus and the Hazel team: people who know Hazel, so no Hazel basics; what matters for writing game-script rules in it. The kids' guide (^du_report(17), the Game Scripts Guide, retro style) stays the kids'; this one is in the Hazel reports' own style. ALSO (his additions): explain the current design of Globals, Cmd, Event and the other structures a rule touches; consider unique IDs for places, objects and people that are human readable and unambiguous in one global keyspace (no bare 1 for a place and 1 for an object); cross-reference Fumola (fumola.org: symbols, times, names as structure) and Adapton (adapton.org: names, nominal memoization). AND (his last addition): from the unified address for any thing, place or person, propose new Hazel types: Globals, RuleState (his name for the per-rule view), and Cmd. AND: templates vs placed instances: a person, place or thing as a template (placed nowhere) and as placed, owned by a place in some state of the game, with ownership able to change (moves, pick up, carry). AND: the world keeps a buffer of addressable instances that were placed and are now removed (in play or in editing), so one can be re-placed later as itself, not as a new instance from its template. AND: frame it against Fumola's store, structured by space and time, each a nesting symbolic structure; MUDU's state uses the space side (nested symbolic addresses) and not symbolic time, for now: that difference stated. | Matthew, 2026-10-25 07:40, in chat: "Thanks for clarifying how it works --- the game engine is running the handler in a special context where that one hatch flag is disambiguated -- I think we should draft and create a Hazel report explaining: * how to author these game scripts, and in particular, the current structure of Globals, and how it's not as global as it sounds --- it's really a subset of all globals, tailored for that rule. * so why doesn't each room define its own version, call it "RoomState" (or something like that, and drop the word "Globals", in that context at least). * there probably _should_ be a structure called Globals, and for debugging/diagnostic purposes, or even advanced game mechanics, it maybe useful for every room to also be able to peek at that full set of Globals, if needbe. In either case, we should define it (as a Hazel type, not just as JS code or JSON structure), and document it in our report on writing these game scripts. * related --- we developed this game in waves that never re-factored the way we represented or termed things in the past --- we have "backgrounds", which became the basis for "world squares" --- the code talks about "Places" but that's not in the UI anywhere. * We should consider ways of consildating the number of distinct notions, and make a simpler system for the current game mechanics, and future games we create within the system. Having a unified notion of "place", perhaps as a kind of path (which top-level world, which square, which place/room/sub-room within that square?) --- let's map how such a unified address system for "place" would work, given the variety of random walks we can do today (assuming all trap doors and passageways are activated as passable)." Then, 07:41: "BTW --- we have a game script how to report already, but it's for kids and meant to use certain retro sytles in its presentation. For this report, the first reader is myself; then Cyrus and the Hazel team --- people that know what Hazel is and just want to know how it's relevant for writing game script rules." Then, 07:44: "the report being created now should explain current design of: * Globals * Cmd * Events, and other structures relevant for a game rule. the report should consider the way places and objects and people could all have unique IDs that are: * human readable * not ambiguous in a global keyspace (so can't just use 1 a certain place, and then 1 for some object) Cross-reference with ideas from Fumola (fumola.org) and Adapton (adapton.org)." Then, 07:44: "Finally, based on a unified way of addressing any "thing/place/person" in the game, we should offer a new representation of Globals, and RuleState for Hazel, and Cmd too." Then, 07:45: "please use images (SVGs ideally?) in the report, to make it more interesting to look at." Then, 07:46: "there's also a distinction between: * person/place/thing as a template (not placed anywhere) * and placed, so that the place "owns" that one, at least in some state of the game (dynamic changes are possible)" Then, 07:47: "the game world itself should probably also have a buffer of addressable stuff that's been placed, but in the current game/edit state, has been removed, temporarily, to be re-placed, potentially, later without a new instance from a template." Then, 07:48: "Fumola as a store structured by space and time --- and each can use symbolic structure that nests -- we don't need symbolic time, yet --- that's one diff between Fumola store and MUDU state, for now." |
^ticket(611) | dress up: a 🌍 Start World button beside Start over: the start world's start square, the friend put there, and a pop-up saying what the game is now (a WIP world: stuff and people, but no interactive people (they are background animations, not quite NPCs) and no puzzles yet; scripting next; feedback welcome); a pointing hand 👉 floating on the button, as an in-game tutorial would; and a WIP ^du_report on the new-player experience, R's phone visit its backstory 🪷 blocked on Matthew low priority dress-up | dress up: a 🌍 Start World button beside Start over: the start world's start square, the friend put there, and a pop-up saying what the game is now (a WIP world: stuff and people, but no interactive people (they are background animations, not quite NPCs) and no puzzles yet; scripting next; feedback welcome); a pointing hand 👉 floating on the button, as an in-game tutorial would; and a WIP ^du_report on the new-player experience, R's phone visit its backstory | Matthew, 2026-10-25, in chat: "mint and enqueue --- low priority --- Better \"first time user\" experience --- Next to \"Start Over\" button, offer \"Start World\" button that: * selects the \"start\" square from the \"start\" world, if any -- the current default world has one. * places the friend into that square, as if they selected it from the world design grid. * presents a pop-up explaining: * Messed Up Dress Up is a WIP, evolving from an activity into a full game world, gradually. * Currently, the game world has stuff in it, but no people or puzzles. It's a place to explore, and evolve into something more dynamic. Current work is focusing on ways for end-users to script their own adventure world system. One baby step at a time. Feedback welcome!" Then: "when we say that the world has \"no people\" -- perhaps instead we should say \"no interactive people\" -- -they are not quite NPCs, more like background animations still." Then: "okay, and as we refine this \"new user experience\", let's have a WIP du_report about it, and this first step of it. The backstory is my friend (let's call him \"R\"), tried the game on his mobile phone and got confused about how to enter the world and do stuff. It's not obvious at all at the moment. So another thing could be to emphasize that \"enter world\" button, with something overing over it (like a \"hand pointing\") emoji, floating on it. Like an in-game tutorial might have." |
^ticket(613) | dress up (tracking, no action yet): why didn't the game catch that M's iPad was slow, and why must the scenery's stillness be set by hand? (its friend drawing takes 1.5 ms, under the 6 ms test, and its late frames did not trip the choppy test, yet its pond ran at 14 fps); the cave measurements in 🧪 may answer it later tracking dress-up | dress up (tracking, no action yet): why didn't the game catch that M's iPad was slow, and why must the scenery's stillness be set by hand? (its friend drawing takes 1.5 ms, under the 6 ms test, and its late frames did not trip the choppy test, yet its pond ran at 14 fps); the cave measurements in 🧪 may answer it later | Matthew, 2026-10-25, in chat: "and mint a ticket (for tracking, not new actions): why didn't we catch that the ipad was slow before? why must we set this manually? maybe the cave measurements will help answer, later or in the future." |
^ticket(633) | dress up: ^du_report(21), the dungeon rooms and the friend from every side: every costume from above (front, side, back) and asleep in the tent, the dungeon room's looks and ways, what each view draws 🪷 blocked on Matthew report dress-up | ^du_report(21): a report to see all of today's design work: the dungeon room (looks, the four kinds of way, holes, the ledge), every costume drawn from above in three facings and asleep in the tent, and what each view draws, before and after. | Matthew, 2026-10-26, in chat: "these new views of each costume are great. please do a du_report with a way to see all of this design work. Thank you, BTW." |
^ticket(634) | dress up: agent-instructions.md cut from 380 KB to a short checklist; the explanation moved to a new public report, ^du_report(22), readable by people and agents (who decides, releasing, 60 fps, design rules, the code, testing) 🪷 blocked on Matthew docs report dress-up | ^du_report(22): how Dress Up is made, for people and agents alike, and agent-instructions.md cut to a short checklist that links into it (it was 380 KB, "not human digestable"). | Matthew, 2026-10-26, in chat: "let's revise this file. Make it way shorter, please." (agent-instructions.md) Then: "we also have reports that are public --- can we put some stuff in there rather than here, and make it human digestable? This file is not human digestable." "a new report, where both humans and agents can read it? du_report" |
^ticket(635) | hazel reports: ^report(34), the pros and cons of an official Hazel JS library (#2711, #2719): for game scripting (MUDU's 📜 rules) and for other uses beyond 🪷 blocked on Matthew report hazel | ^report(34): an official Hazel JS library? The pros and cons of making Hazel-as-a-JS-library (#2711, #2719 and the embed frame) official: what MUDU's game scripting has shown, what other uses it would serve (pages that run or check Hazel, teaching sites, embedded editors, other games), and what it would cost Hazel to keep (an API to support, builds, versions, the evaluator's semantics exposed). | Matthew, 2026-10-26, in chat: "let's write a Hazel report about the pros and cons of creating an official Hazel JS library for these game script use cases, and other use cases beyond." |
^ticket(642) | hazel: the landing order for livelits — #2469 to dev first, then retarget #2635 to dev 🪷 blocked on Matthew meeting 2026-11-04 hazel meeting | #2635 targets #2597's branch, which targets the stale integration/livelits-splicerefs (no open PR). Plan with the team: #2469 (Andrew's, not ours to merge) lands on dev; then #2635 is retargeted to dev, showing only the livelit diff (~70k lines, 442 files); #2597 closes into it. Out of draft once the description says what reviewers should read. | Matthew, 2026-10-29 09:0x, in chat: "today is a special work day, where we as a team are trying to coordinate more tightly, and merge PRs that are ready, in some order. ... let's look at our PR for livelits and modular editors, and decide how ready it is. People will want to know"; then "please update dashboard with our new tasks and focus for today". |
^ticket(650) | hazel: #2718 (Negabinary: unused warnings for theorems and forall binders): can we help with 7h3kk1d's requested changes? parked hazel | 7h3kk1d requested changes on #2718 at 18:54Z. Not our branch: help by checking his claims and prototyping his suggested ~warn_unused fix to hand to Negabinary (as a comment or a PR into fix/theorem-unused-warnings, with Matthew's OK). | Matthew, 2026-10-29 13:0x, in chat: "let's look at what's current here https://github.com/hazelgrove/hazel/pull/2718" then "can we help in some way?"; parked by "new agenda: let's look at #2672". |
^ticket(654) | hazel merge day (10-29), end of day: your approvals and the Slack post 🪷 blocked on Matthew hazel | Before signing off: approve #2756 (Cyrus: advisory perf report; review notes on ^ticket(652)) and #2626 (disconcision: faster editing commands; notes on ^ticket(653)), then post the end-of-day Slack message, which says both are approved. | Matthew, 2026-10-29 14:5x, in chat: "what should I do next, with my limited human attention. I'd like to sign off in 30min or less"; then "Yes: review #2626 now (ticket + notes), and draft the end-of-day Slack message while I approve #2756." |
^ticket(655) | hazel: where things stand after merge day (2026-10-29), to keep track queued tracking hazel | Matthew's tracking ticket for the state of things at the end of merge day: what landed, what waits on whom, and what to pick up next. Update as the threads move; close when they are all settled. | Matthew, 2026-10-29 15:4x, in chat: "let's make a hazel ticket for me to keep track of the state of things from today." |
^ticket(664) | hazel, the meeting with Cyrus on Wed 2026-11-04: a list of specific tickets to grind on together queued meeting 2026-11-04 🪷 blocked on Matthew hazel performance meeting | Tickets for Wednesday. Find or create a list of specific tickets to work through with Cyrus. Two to start: (1) the cost of undo, and ways to make it O(log n) per edit and per undo rather than O(N), as it seems to be now; (2) related: how much sharing is lost as data passes to and from the worker thread. | Matthew, 2026-11-02 07:06, in chat: "after we do this chore, I also want to find/create a list of specific tickets to grind on together for meeting Cyrus this Wed. * investigate the cost of undo, and potential ways to do it in O(log n) time per edit and per undo, not O(N) time, which seems to be the way it was working. * related to undo --- how much are we loosing sharing as we pass data to and from the worker thread?" |
^ticket(665) | hazel, performance: the cost of undo, and O(log n) per edit and per undo instead of O(N) queued meeting 2026-11-04 hazel performance meeting | Undo in O(log n). Measure what an edit and an undo cost as the program grows, and design undo so each costs O(log n), not O(N). Today, on #2635 (src/web/app/History.re): the undo and redo stacks hold whole Page models, capped at 250. Pushing compacts the previous head: it drops the derived caches (syntax, statics, evaluation) and keeps the zippers. The newest entry stays whole (032fe3aca6), so only the latest undo restores without rebuilding. Any other undo rebuilds syntax from the zipper (incrementally, through the live editors' caches), re-analyzes from CachedStatics.empty and re-evaluates; on Full Body that was about an edit's time (10-15). Where the O(N) is, to measure: the restore's re-measure and re-parse walk, whole-program statics from empty (per-item DefStatics cannot reuse anything), full re-evaluation; per push, compact_head (per cell), the cap's List.filteri over 250, the result's persist/unpersist. Directions: undo as an inverse edit applied to the live state, so derived state updates as it does for a keystroke; or snapshots that keep their derived state and share structure with the live one (per-item statics keyed by item), so a restore recomputes only the items that differ. | Matthew, 2026-11-02 07:06, in chat (from ^ticket(664)): "investigate the cost of undo, and potential ways to do it in O(log n) time per edit and per undo, not O(N) time, which seems to be the way it was working." |
^ticket(666) | hazel, performance: how much sharing is lost passing data to and from the eval worker queued meeting 2026-11-04 hazel performance meeting | Sharing across the worker boundary. How much structure sharing and identity is lost as data goes to the worker and back, and what that costs. Today, on #2635: within one message, Marshal keeps the message's own sharing. Across messages, ShareCodec (993e3d5f91, 2b080af683; ^ticket(513)) keeps a table on both sides, keyed by Merkle hash: a value already sent goes as a reference, so the worker's request shares unchanged values with the last one. Responses can be shared the same way (ServerMessage.Shared). What is still lost, to measure: values under ShareCodec's min_size (16), first sends, and everything after a table reset; and on the main thread, every value decoded from a response is a new object, so identity-keyed memos (TypHash's and ValueHash's WeakMaps, the view memo, MapPiece identity) miss on it and hash it again. Measure per request and response: bytes with and without sharing, the share hit rate, encode, decode and hash time, and the identity misses on the main thread caused by decoded values, for a Kids' Choice release, a Full Body edit and an undo (an undo's old values: are they still in the worker's table?). Related to ^ticket(665). | Matthew, 2026-11-02 07:06, in chat (from ^ticket(664)): "related to undo --- how much are we loosing sharing as we pass data to and from the worker thread?" |
^ticket(667) | hazel, performance: why #2635's evaluator takes half dev's steps on the PerfBudgets program queued meeting 2026-11-04 hazel performance meeting | Half the steps. Dev's new PerfBudgets test (#2678, Cyrus) counts the evaluator's trampoline steps on a fixed program: 206,834 on dev (10-12), budget 227,000. On #2635 after ^ticket(663)'s merge it is 96,438, and the edit re-run 270 against dev's 378. Find which change does it: #2469's evaluator work, ours (evaluate_open, the ascription hash, the spine memo), or a difference in what is counted (a fast path that does not go through the counted trampoline). If it is real, it is an improvement to take to dev; if it is the counter, PerfBudgets should count it. | Found 2026-11-02 merging dev into #2635 (^ticket(663)): PerfBudgets 0 and 1 failed for being more than a quarter under budget; the budgets were lowered on #2635, as the test asks. |
^ticket(668) | hazel, Hazlet, npm: a prototype npm package of Hazel as a JS library, installable and documented the npm way meeting 2026-11-04 hazel meeting | Hazlet on npm. What does it take to publish a prototype npm package that other people can install (npm install hazlet) and use, documented the way npm packages are? A Hazlet (Matthew's word, 2026-11-02) is Hazel embedded as a library in a JS program's event-handler system; Messed Up Dress Up is the first and only one so far, through the draft library hazel-lib.js (#2711, with #2719 stacked on it; ^report(34)). The discrete tasks, each its own ticket: (1) ^ticket(669) the package's build: the release bundle of #2719 wrapped for node (require and import) and the browser (a script tag, from a CDN that serves npm); (2) ^ticket(670) TypeScript declarations for the API and its value mapping; (3) ^ticket(671) the README, the npm way (install, quick start, API, values, limits, license), and a CHANGELOG; (4) ^ticket(672) examples and a check that installs the packed tarball into fresh node, browser and TypeScript projects (on GitHub: no headless browser here); (5) ^ticket(673) the name, the license, the version scheme and who publishes (an npm account is Matthew's: Claude cannot log in); (6) ^ticket(674) Dress Up loads its Hazel from the published package instead of a branch build. Order: 669 first; 670 and 671 on its API; 672 checks all three; 673 decides before the first publish; 674 after it. Open question for the meeting: is the package the library alone (Hazel.run and friends), or also the Hazlet pattern itself, a helper that turns a program of modules into JS event handlers as Dress Up uses it? | Matthew, 2026-11-02, in chat, under the agenda's Hazlet item (^report(37)): "can we add a task for you: What does it take to create a prototype npm package that other people can download and use via npm, that's documented the way that npm documents things, etc? for each discrete task, please create tickets that inter-link with each other"; and: "if it's possible to register our \"Hazlet\" work today under npm, I'd like to try that" |
^ticket(669) | hazel, Hazlet, npm: the package's build (hazel-lib.js for node and the browser) queued meeting 2026-11-04 hazel meeting | Hazlet package: the build. Part of ^ticket(668). A folder with package.json and the release bundle of hazel-lib.js from #2719 (one js_of_ocaml script that defines Hazel on the global object; about 2.7 MB unpacked, 643 KB gzipped, ^report(34)), plus thin entry points: require("hazlet") and import Hazel from "hazlet" in node give the Hazel object, and the same file works as a plain <script> from unpkg or jsDelivr. package.json the npm way: name, version, description, keywords, license, repository, homepage, bugs, main, exports (require, import, types), files, engines. Check: npm pack gives a tarball whose contents are only those files; node runs the README's quick start from it. Feeds ^ticket(670) (types), ^ticket(671) (README) and ^ticket(672) (install check). Where its source lives (a folder on #2711's branch, built by dune, or a repository of its own) is part of ^ticket(673). | Matthew, 2026-11-02, in chat, under the agenda's Hazlet item (^report(37)): "can we add a task for you: What does it take to create a prototype npm package that other people can download and use via npm, that's documented the way that npm documents things, etc? for each discrete task, please create tickets that inter-link with each other"; and: "if it's possible to register our \"Hazlet\" work today under npm, I'd like to try that" |
^ticket(673) | hazel, Hazlet, npm: the name, license, versions and who publishes queued meeting 2026-11-04 hazel meeting | Hazlet package: name and publishing. Part of ^ticket(668); decisions for Matthew, some for the meeting with Cyrus. (1) The name: unscoped hazlet (free as of 2026-11-02 10:17), under Matthew's npm account, or a scope such as @hazelgrove/hazlet (needs an npm organization; @hazelgrove has no package now). (2) The license: MIT, as Hazel's package.json has. (3) Versions: 0.0.x while experimental, each naming the Hazel commit it was built from (Hazel.build and the CHANGELOG); dist-tags. (4) Who publishes: the account, its two-factor login, other maintainers; later a GitHub workflow with an npm token (a secret Matthew sets) and provenance. Claude cannot create the account or log in; Matthew runs npm login, then npm publish or says to. (5) Where the source lives (^ticket(669)). The first publish waits on ^ticket(669), ^ticket(671) and ^ticket(672); ^ticket(674) waits on it. | Matthew, 2026-11-02, in chat, under the agenda's Hazlet item (^report(37)): "can we add a task for you: What does it take to create a prototype npm package that other people can download and use via npm, that's documented the way that npm documents things, etc? for each discrete task, please create tickets that inter-link with each other"; and: "if it's possible to register our \"Hazlet\" work today under npm, I'd like to try that" |
^ticket(675) | hazel, Hazlet, report 34: a live trap room in the report, its Hazel rule editable in tiles meeting 2026-11-04 hazel meeting | A live trap room in ^report(34). The reader plays Messed Up Dress Up's trap room on the report's page and edits the room's Hazel rule in Hazel's tiles, the room answering the edited rule at once. Three pieces, each its own ticket: (1) ^ticket(676) the trap room on a page that is not the game's; (2) ^ticket(677) Hazel's tile editor on that page; (3) ^ticket(678) the report's page wiring them to hazeljs (^ticket(668)): the editor's text, Hazel.runProgram, the rule handed to the room. Today the game does all three inside itself (its Scripting panel), so a first version can be an iframe of the game opened at the trap room; the package version is the Hazlet pattern shown working in a page we write. | Matthew, 2026-11-02, in chat: "Once we publish hazeljs and mudu as npm packages, can we use those here? So the reader can: * see the trap room and * edit the hazel script, with tiles, etc? https://matthewhammer.org/hazel/reports/034/" |
^ticket(676) | hazel, Hazlet, Dress Up: the trap room on another page (a deep link, then a messed-up-dress-up package) queued meeting 2026-11-04 hazel dress-up meeting | The trap room outside the game. Part of ^ticket(675). First step, small: a link that opens the game at the trap room with its Scripting panel showing and Hazel chosen (the game reads ?try=cave-N and ?logic=hazel today, but has no way in to the trap room), so a report can frame it. Then, for the package route: the game as an npm package, messed-up-dress-up (free on npm on 2026-11-02; mudu is someone else's), exporting the trap room (its drawing, its events, the commands it runs) for a host page to mount and to hand a rule. That needs the room pulled out of the game's shared global state (about 30 script files), so it is the larger step. A Dress Up release each, the speed run as the check. | Matthew, 2026-11-02, in chat: "Once we publish hazeljs and mudu as npm packages, can we use those here? So the reader can: * see the trap room and * edit the hazel script, with tiles, etc? https://matthewhammer.org/hazel/reports/034/" |
^ticket(677) | hazel, Hazlet, embed: Hazel's tile editor in another page (embed-editable as a PR, and served for a report) current meeting 2026-11-04 🪷 blocked on Matthew hazel meeting | Tiles in a page. Part of ^ticket(675). Embed mode (#2719) shows a posted program in Hazel's tiles, read-only; the embed-editable branch (12 commits, no PR yet) makes it selectable and editable. Open its PR, stacked on #2719 (^report(34)'s step 2). Then serve it where a report's page can frame it: a branch build URL, a copy of the app's files beside the report, or a package of its own. To check: whether a CDN that serves npm packages serves the app's index.html as a page at all. The library package (^ticket(668)) does not include the app: hazel-lib.js has no editor. | Matthew, 2026-11-02, in chat: "Once we publish hazeljs and mudu as npm packages, can we use those here? So the reader can: * see the trap room and * edit the hazel script, with tiles, etc? https://matthewhammer.org/hazel/reports/034/" |
^ticket(678) | hazel, Hazlet, report 34: the report's page wires the room, the tiles and hazeljs queued meeting 2026-11-04 hazel meeting | The wiring. Part of ^ticket(675), after ^ticket(676) and ^ticket(677). The report's page posts the trap room's module text (and Common's) to the tile editor, takes each edit back by postMessage, runs the program with hazeljs's Hazel.runProgram (^ticket(668)), and hands the new on_event to the room; errors, holes and unfinished brackets shown beside it, and the rule kept while it is not ok, as the game's panel does. A dated update in ^report(34) shows it. | Matthew, 2026-11-02, in chat: "Once we publish hazeljs and mudu as npm packages, can we use those here? So the reader can: * see the trap room and * edit the hazel script, with tiles, etc? https://matthewhammer.org/hazel/reports/034/" |
^ticket(681) | hazel, Hazlet, performance, report 34: convert JS values directly at the call boundary, and a report measuring what it saves queued hazel performance | Convert JS values directly. ^report(34)'s What next, step 4: convert JS values directly into Hazel values at the call boundary, not through syntax re-evaluated (^report(25)'s floor), and merge #2681, which the game's typed rules need. Then a report measuring the savings in time and space, if possible: per call and as the passed value grows, against #2719's library as it is now. Builds on ^ticket(539) (of_js producing final values: trial branch lib-floor, CI green, waiting on Matthew's call), next to ^ticket(551) (a passed world converted once, as a handle) and ^ticket(547) (handing JS the closure). | Matthew, 2026-11-03, in chat: "let's also enqueue a ticket to work on. Mint a ticket for this step: Hazel reports, ^report(34), What next, step 4: \"Convert JS values directly\". http://matthewhammer.org/hazel/reports/034/#step-4a and write a report measuring the savings in time and space, if possible" |
^ticket(683) | hazel, Hazlet, dress-up: what a Hazel edit box gives over a JS one: typed completion and errors in place queued hazel dress-up | Hazel edit boxes over JS ones. Two advantages to make real in Messed Up Dress Up's tiles, and to say in hazeljs's README: (1) type-directed menus: Hazel's editor already suggests from types (TyDi, src/haz3lcore/TyDi): after a dot, the labels of the value's type (dot_labels); where the expected type is known, the variables of that type first; then forms and operators. (2) better errors: each error marked at its term with what was expected and what was found, ExplainThis for every form, and the program still running around the error, so the game keeps going; for a rule that runs but answers wrongly, probes (each expression's value as it ran) and the event log. To find out first: what embed mode (embed-editable) shows of these: it is a pared-down view, and whether it draws the suggestions, the cursor inspector and probes has not been checked. | Matthew, 2026-11-03, in chat: "potential benefits of hazel edit boxes over JS ones: * can we provide better type-directed menus for editing? (dot completion based on types?) * can we provide better error messages when the hazel snippet does not work as expected?" |