Lab note #065 Scheduler Retrospective

Lab note #065 Scheduler Retrospective

These weeks are passing by faster and faster. I too would like to work faster, but I didn't think vibe coding was going to be it. I work with AI everyday, and I mostly have it do basic debugging or explaining Python minutiae to me. I know what it's capable of. However, YC claims much of the code in the current batch are being vibe coded and when playing with Codebuff and Claude Code, I recognized it was a leap forward. I'm always up for trying new ways to work, so I tried generating the scheduler. It's cost me about a week and a half's worth of time, cleaning up and understanding what it did.

This week, I spent most of the time pushing on and cleaning up the scheduler. I found that there were a lot of minor design choices that I wouldn't have made on closer examination (and I wouldn't have made them for very specific reasons!) I still think AI-assisted programming is still valuable, but it's not going to be the panacea everyone makes it out to be, as impressive as it is.

Simon Willison also clarified what Andrej Karparthy meant by vibe coding–namely, that not all AI-assisted coding is vibe coding.

There’s a new kind of coding I call “vibe coding”, where you fully give in to the vibes, embrace exponentials, and forget that the code even exists. It’s possible because the LLMs (e.g. Cursor Composer w Sonnet) are getting too good. Also I just talk to Composer with SuperWhisper so I barely even touch the keyboard.

I ask for the dumbest things like “decrease the padding on the sidebar by half” because I’m too lazy to find it. I “Accept All” always, I don’t read the diffs anymore. When I get error messages I just copy paste them in with no comment, usually that fixes it. The code grows beyond my usual comprehension, I’d have to really read through it for a while. Sometimes the LLMs can’t fix a bug so I just work around it or ask for random changes until it goes away.

It’s not too bad for throwaway weekend projects, but still quite amusing. I’m building a project or webapp, but it’s not really coding—I just see stuff, say stuff, run stuff, and copy paste stuff, and it mostly works.
- Andrej Karpathy

Vibe coding should be for when projects are low stakes, with low security requirements, and your money isn't on the line. But obviously, that's not what people are doing. A lot of people, both experience and novice programmers are accepting everything as it's generated.

I think I saw this once in Job Simulator.

AI-assisted programming isn't going away, and it'll be what most people call vibe coding, despite its original intent and definition. But I think the human still needs to drive the process. Abdicating direction and responsibility will look like it works in the beginning for a little bit, and all the incentives might be to just ship what kinda works in the name of speed and product market fit. But I suspect this will be just a different kind of technical debt that people will find when the chickens come home to roost.

The thing I'm wrestling with right now is how to indicate when something is an async computation. The obvious choice is native async/await, but I had hesitated on doing so because:

  1. I wanted to be able to cancel long-running async promise, and in Javascript you couldn't.
  2. I wanted to leave room in my design for multiple-resumption in my algebraic effects. This was really the whole reason for embarking on a scheduler in the first place.
  3. I didn't think people would find an enforced async to be intuitive for a computational graph.

But after turning this design space over and over, #3 might just be fine if I just tell people: "hey this is an async computational graph, because it supports async effects". And it turns out #1 is false because in Python, you can cancel futures (its name for promises).

So I'm left with a couple options.

  1. Every reactive function returns a wrapped type ReactiveValue[T]. This is like using a Free Monad to construct a description of the computation. But that leaves a lot of work to work out how to compose these things together.
  2. Use with and write a kind of "do-notation" for waiting for async values to resolve. This is like just re-implementing await all over again.
  3. Go with the native async/await.

It's impossible to make it completely transparent, short of writing my own language, because the fundamental assumption in program evaluation for most any language is that you can't intercept a call to a function and suspend that execution–unless it's awaited. And perhaps you want that distinction, so users are aware, just as they need to be aware of what effects are being raised for controlled state manipulation.

Given everything, I'm leaning more towards #3, despite having sunk-costs. The original reasons for embarking on a custom scheduler seem less compelling, now that I've learned more. Futures are cancelable, async reactive computation isn't such bad UX if you tell devs up front, and multiple resumptions isn't currently a hard requirement.

The only current application for multiple resumption is a simpler handler for websocket pushes. So I can't quite justify this direction any longer. Psychologically, I'll have to take the loss, and tell myself to take the longer view. Look, there's other hard problems already visible, and you don't need the win on this one. The longer you fight it, the more time will be lost.

Here's the interesting links that I looked at this week.

  • Continued learning all about bifunctors and function objects and exponentials in category theory.
  • What is PLUS times PLUS? In my post on visual programming, I was looking for that visualization of lambda calculus, but couldn't remember the name. This week, I found someone made an explainer video on Tromp Diagrams.
  • Categories for AI 1: Why Category Theory? A light intro explainer on a category theory course. The thing interesting here was the Optics category that helps with bidirectionality. I'd run into it in Cambria for schema migrations, but I think it might help for visual programming UI as well, so that you can edit the code and change the visuals or vice versa. In addition, it mentioned sheaves, and hints that it's a way to help understand how global effects arise from local effects. This seems related to complex systems, but I'm not sure...
  • React 2014 : What does it mean to be Reactive? Erik Meijer frames the push and pull of reactive systems as a type system. Super interesting given what I'm doing right now. Maybe I should revisit this despite declaring on giving up on the scheduler. 🤔
  • What is a (side) effect? A pondering on what side effects are. I thought of it differently after this talk.