Building Frameworks Building Systems

Style's Scaling Challenge: From 4 to 200 Interactives a Year

The speaker opens with a content warning about YAML and introduces Style's recent acquisition by Curriculum Associates, which brought new customers, projects, and a push to expand from science into maths classrooms. This expansion demands scaling interactive game production from just 4 per year to a promised 200, migrating an existing backlog, and fixing accessibility issues—all without growing the engineering team.

A Self-Deprecating Intro and a Look at Interactive Content

The speaker jokingly introduces himself as someone who likes to have a hand in every project, setting up the story of being told to step back. He contrasts dry static question content with engaging science and maths interactive games, explaining that interactives typically serve as supplementary practice or application tools within a lesson.

Reframing the Problem: Code as Content and the Lambdas at Home Schema

Facing the challenge of building 200 interactives a year, the speaker argues the team should stop caring about the code itself and focus instead on maintainability, brand aesthetics, and accessibility, treating code as a form of data. He introduces his side project, Lambdas at Home, a YAML schema for defining functions with metadata, executors, arguments, and tests so that the underlying implementation—run locally via models like GPT OSS or Kimi k2.5—becomes interchangeable and verifiable.

Building the Interactive Pipeline: Bootstrap, Migration, and Deployment

The speaker explains how the Lambdas at Home concept was applied to interactives: running, dockerizing, smoke testing, deploying, and improving arbitrary JavaScript/HTML blobs, likening each step to a bounded verification problem for an LLM. He details the bootstrap phase—discovery, making the interactive standalone by migrating external references, setting up CI/CD, and uploading assets to a CDN—while emphasizing minimal changes to preserve the original artifact's integrity, and shows the underlying Rust-based prompt/check/reprompt loop.

The Improvement Pipeline: State Machines and Automated Accessibility

The speaker outlines the second, improvement phase of the pipeline, where the system explores an interactive by building a plausible state machine of student interactions, backtracking and repeating to map all reachable states. These states are then used to auto-generate tests and drive modifications via internal critic frameworks, ultimately producing fully accessible interactives with screen reader and keyboard support with minimal human intervention.

Problem One: Taming Boilerplate Drift with Armchair General

The speaker admits the pipeline works well but that people, not the AI, become the real bottleneck, starting with keeping testing boilerplate in sync. He describes Armchair General, Style's homegrown Git-based build coordination tool that defines deterministic build graphs of 'products,' and shows how a new YAML-driven, safely vibe-coded scripting concept was added to it—noting the biggest challenge was aligning with subject matter experts rather than the implementation itself.

Problem Two: Rebuilding the Autoscaler as Rasputin

With interactive PRs stuck waiting on build agents, the speaker describes rewriting the team's autoscaler in a single day using AI assistance, humorously naming it Rasputin. The new system removed the previous cap of about 800 concurrent builds, included a 'zombie killer' to handle buggy agents, and delivered built-in logging, tracing, and observability, enabling much greater build parallelism.

Problem Three: Overhauling the Merge Queue with Batchbrew Simulations

Even with builds fixed, PRs took hours or days to merge company-wide, so the speaker built a simulator integrating Git, mocked BuildKite, and GitHub to run Monte Carlo tests on new merge-queue strategies without risking production. Using Armchair General, he parallelized the team's homegrown merge queue (Batchbrew) by grouping mutually exclusive PRs, clearing the entire backlog and cutting 90th-percentile merge time from about sixteen hours to under three minutes.

Results and Reflections: 250 Interactives Shipped and the Case for Responsible AI

The speaker summarizes how AI-assisted tooling—applied responsibly across build systems, autoscaling, and merge queues—lifted the entire engineering team, not just his own interactive work, enabling the migration and deployment of 250 interactives (mostly backlog, some new maths content) with essentially one engineer. He closes by cautioning against dismissing AI-generated code outright, arguing instead for using it to empower colleagues and end users, before thanking the audience and mentioning Style is hiring.

Cool. So There's a content warning. There we've got YAML, and we've got YACS in here. So if you're afraid of those, I can't recommend. Style last year was recently acquired by Curriculum Associates, an ed tech company from The States.

It came with a whole bunch of changes, some more subtle than others, more projects, different customers, scaling out our features, so on. One of those changes is expanding our reach from primarily science based classroom audience to also maths. That's meant we've needed to expand our collection of interactive games in our lesson lessons for students and teachers in classrooms.

There's a pretty nifty catch, though. We need to scale out the production of Sims or interactive games from just four a year, a few years ago, to 20 last year, to a promised 200 for a potentially few million students. Oh, but we can't expand our engineering team to do it, and we need to migrate our existing backlog and to get on top of all the accessibility issues with them and then serve all the new interactives.

Enter me. I'm pretty self centered. I love sticking my fingers in with every pie under the sun. This talk is basically entirely about the one time I was told to hold my fingers back for a minute. Those same pies just came flying back at my face. This is some question content in one of our lessons.

You've got a couple questions. They're pretty dry on their own. By contrast, these are some interactive games. This is one science one, and this is one maths one. They're obviously interactive, but I'm not risking any live demos. You'll just have to take my word for it. The best way to think about an interactive in the context of a science or maths lesson is, for the most part, is that it serves a supplementary purpose of the core content itself, its practice or application. And that's that's sort of changing.

Building interactives from the ground up isn't a trivial ask right now, so we really needed a reframe of the problem getting building 200 a year. Really, we don't care about the code itself, we care about being able to maintain them with as little effort as possible. We have a lot of machinery for that in our mono repo already. We just we also have to care about the aesthetics and the accessibility. They have to be representative of our brand, and they have to be inclusive.

Therefore, we have a series of constraints we can improve over time, and the artifact is the code and thus the interactive itself. We essentially encode the code as a form of content, form of data. So Lambdas at Home is a project that I've been working on in my spare time.

It runs on a really simple premise. I want a schema that lets me define a function that can be run wherever I want it, in the CLI, on a server, wherever. Don't care how it runs, when it runs, who runs it. I just need it to be secure. You'll notice that in this YAML, the bulk of the schema isn't actually the code. It's everything else around it.

It's the metadata, the executor, the arguments. It's everything that defines a contract. You can even add tests to it. There's some basic tests here. And once you have that, you actually just realize there's little need to write or read the code yourself here. You sort of just care about the inputs and the outputs, verification, and then you just replace the implementation with anything else.

Personally, on my home server with way too much RAM before RAM's exploded, I run GBT o OSS and a flavor of Kimi k 2.5. So it runs pretty fast and it runs pretty reliably. But given the right scaffolding, security, automatic verification, you get the thing out. It's you're essentially defining invariants for a very specific task in a very specific context.

So we took that concept and applied it to our interactives. In particular, we need to run the interactive. We'll find a way to do that. We need to dockerize it. We need to automatically smoke test it and deploy it and then test it and improve it over time. And this pipeline ought to be able to run essentially any blob of arbitrary JavaScript in HTML.

You can sort of think about this or each step. Analogously is like a a boundary value problem in however many dimensions. As long as you're not asking too much of an LLM by way of constraints and your input isn't too extreme, what you get out on the whole won't be either. Coming back to this diagram though, you might think it's a bit odd that we test it after we deploy it.

Well, not in stand up mode. So start up mode. That's actually because this this this flow is split into two parts. The bootstrapping part and the improvement part. In the bootstrap side of things, we do run discovery.

How do we run the simulation? Punch it into an LLM, some kind of instructions. We verify that runs, opens, returns a port and host, and that there are no errors on launch. Then we gotta migrate it. We gotta make it standalone. If it has references to the SIM outs, everything outside itself, we can't do anything with it.

We gotta copy it in so we can migrate it. And in this regard, we we we do extensive testing to make sure that is standalone. Then we can go set set up standard CI and deployment infra. Upload all the assets because we're moving stuff to the CDN, and then we test out whether it can be deployed.

The entire point of this pipeline is to make as few changes as possible to the target in order to preserve its integrity with the exception of the asset uploading. So this is what it kinda looks like, and this is what the loop looks like. It's probably pretty familiar, although it is Rust. Sorry. The prompt, you got your checks, whatever, reprompting, loop, that kind of thing. The second part of this process is the improvement pipeline, which I'll skip through because it's worth another talk.

We're gonna explore the interactive. We're gonna build a plausible state machine representation as a student. I mean, it's basically evaluating all the available interactive features, interact with the most obvious feature that the interactive is insisting we should, and repeat until some stopping condition. Call the final state, repeat by backtracking, and then repeat the entire process some number of times.

What we then get is a whole bunch of states that we can write tests automatically based on. Use a cheap model. You can use a good model. Doesn't matter. You have a definitive state. Then once you do that, you can run write modifications according to some other critic frameworks that we've got internally.

And what you get out is a fully accessible interactive game with minimal inter intervention. Screen reader support, keyboard support, all that kind of stuff. I didn't have that before. There's just like one really, really big glaring problem with all of this. It's not the one that you'd expect out of a theoretically token burning, hands off self driven pipeline does genuinely perform pretty well and fairly efficiently. It's just like everything else. See, that's the problem.

Everyone else is the problem. I'm perfect. Not really. So problem number one or finger in pie number one. How do I minimize the drift of all the boilerplate that's driving the testing of of the interactives? Some background, our build system is coordinated using a piece of homegrown software called Armchair General.

It's a get back solution that solves the question of, given something that I've got that I need to build, what other things and what files do I need to build it? These things are called products, which can represent a Docker image, a dependency, or test shaped stuff. Again, more YAML, not sorry.

Just got some metadata and some dependencies and some files. The idea is that you chain them and all the file system dependencies together for a fully deterministic build graph depends only on the state of the file system. So the solution here, because this isn't enough, is we build a new concept into it that creates them on the fly, normal YAML, except there is, using safely vibe coded scripts.

Hurrah. This is what that looks like. It's a pretty simple one by comparison. You've got an action script, include some files in order to know how the script runs. The most time consuming thing about implementing this wasn't actually implementing it.

It was talking to everyone who had a better idea and better opinions than I did on the system. And we have some really good SMEs. So that's one bottleneck down. But problem number two or a yak and a shave is my PRs aren't building. They're hanging around awaiting build cat agents, spot instances forever. And, honestly, the solution to this is kind of the engineer's dream. We rewrote the autoscaler in a day and named it Rasputin because I discovered free will.

So that's what that looks like. Previously limited to about 800 at a time. If that sounds mildly dissatisfying, though, that's okay. Naturally, we found other bay bugs in the agents, so we wrote a zombie killer to compensate. So when we had identified what engineers had been thinking about this problem for a long time than I longer than I had and when we decided we'd had it about up to here waiting for builds, And we identified all the problems with the existing autoscaler.

We had targeted fixes that we just wanted to make, so we made them. Clawtrust gave us the ability to do that, like I said, in a day. And what's even better, having written our own auto scaler now is we get all access to logs, tracing, metrics, observability by default because we had the good foundations for them. So we can understand why it's broken.

And we can do more parallelism, which everyone loves. So problem number three, well, that one pie writing yak is, well, I've done. Cool. My PR is building cleanly.

That's great. But my PR is taking hours to merge. Days. And so is everyone else's now that I've locked 50 interactive code PRs over the fence for no one to review, by the way, but it's now in the queue. Surely, it's a transitory problem. Right? Nope. Engineers were also waiting hours and days consistently for anything to merge. So I sketched out an idea, ran it past a few others who had, again, more experience in the area, and it was a resounding yes.

So for some background, we home brewed our own merge we home brewed our own merge queue. Batchbrew. It's a genuinely brilliant piece of software, but it hasn't really been scaling to our increasingly multifaceted, monorepo esque needs for a variety of reasons. So I I vibrated a simulator for it, one which integrated Git, mocked BuildKite, and GitHub, and allowed us to conduct some Monte Carlo simulations on new strategies to evaluate their effectiveness.

Importantly, I didn't wanna make changes to our merge queue in production. I I didn't wanna piss off the other engineers when I inevitably broke it. So developing a good testing ground was incredibly important. And then using the power of armchair general, as I explained before, I parallelized batch brewer. Technical details will be somewhere else, I'm sure, by group grouping mutually exclusive overlapping PRs and being smart about when we throw away work.

And you can see the results here. That's my maniacal laughter. Ignore. We got to the end of our dependency backlog. Some happy people. We got to the end of our complete like, got to the back of our backlog. Stuff merged in ten minutes, and my interactive PRs merged.

And so that's one more bottleneck down. For anyone who likes graphs, this is our the red line, the red smooth line is our ninetieth percentile time to merge in minutes. That's sixteen hours for ninetieth percentile PRs to merge. We got that down to less than three.

So you should start seeing a pattern here. We've used AI for bolstering our ability to make changes responsibly, safely, and consistently using the patterns that I've shown that lift up the entire engineering team, not just my interactive stuff. And then they let us ship to soon to be millions of of students. The bottlenecks are moving back and back.

And, ultimately, what we unlocked through these changes is many, many interactive games using an artifact shipping framework. We've migrated and deployed 250 interactives, a number of which are maths and some of which are our existing backlog. Oh, sorry. Most of them are our existing backlog. It wouldn't been wouldn't have been possible to do in the same time frame and as few engineers, me.

Otherwise, without this without the systems and frameworks that we already had and improved on and built. They effectively built themselves here. But but but but but it's far too easy to sell ourselves short here. We must not seed good engineering practices to locking out AI generated code left, right, and center unless you intend for no one to review them.

And now more than ever, there's increasing incentive to use it to serve our own colleagues, ultimately consumers in ways that not only benefit them now, but pave their pathways to do more good too if we let them. If any of these problems looked interesting to you, there are so, so many more where they came from and a lot more to them that I've not jumped into here.

And we're hiring. A handful of us from Style are here, and I promise we don't bite much. Thank you.

AI Engineer

MELBOURNE

Google Cloud Google DeepMind

AI Engineer Melbourne event branding with Google Cloud and Google DeepMind as flagship sponsors, and four QR codes for event interactions.

Stile

Content Warning: YAML and Yaks ahead.

Stile

The Acquisition'n'me

The Acquisition'n'me

Stile is expanding from just Science into Maths

The Acquisition'n'me

  • Stile is expanding from just Science into Maths
  • Going from shipping 4 interactive games per year to 20 last year to 200 this year.

The Acquisition'n'me

  • Stile is expanding from just Science into Maths
  • Going from shipping 4 interactive games per year to 20 last year to 200 this year.
  • Buuuuuttt....
    • We can't expand the eng team
    • We need to migrate the existing ones
    • We need to make them all accessible

Stile

Stile

A large, blank white area occupies most of the slide, likely intended for content display, under the heading 'Stile'.

How 2 Build an Interactive

How 2 Build an Interactive

Screenshot of an interactive lesson platform interface, branded "Stile", showing two question components. The left component is a text-based question: "List two examples of a solid changing to a liquid." The right component is a multiple-choice question: "Which of the following can cause matter to change from one state to another?" with options for "A change in temperature", "Adding water", "Applying pressure", and "Gravity".

How 2 Build an Interactive

Hey there! Let's use the mad scientist's evil invention to change the temperature and observe what happens. 🤯🔥🧊

An illustration of an interactive game interface. It shows a cartoon character avatar in the foreground with a speech bubble, set against a backdrop of a lake and mountains. A blurred controller-like device with a temperature gauge is visible at the bottom right.

How 2 Build an Interactive

A screenshot of a white application interface for building interactive content, featuring a main canvas area, a toolbar with icons like a grid and a design tool, and pre-defined text boxes below that read "a x b = ?", "a x b = c", and "c".

How 2 Build an Interactive

Interactives supplement lesson content

How 2 Build an Interactive

  • Interactives supplement lesson content
  • Non-trivial
  • Needs to represent our brand

How 2 Build an Interactive

  • Interactives supplement lesson content
  • Non-trivial
  • Needs to represent our brand
  • Needs to be inclusive

Lambdas at Home

Define a function to run locally or remotely, with a schema.

Lambdas at Home

Define a function to run locally or remotely, with a schema.

functions:
  - name: echo
    # ...
    executor:
      kind: RubyWasm
      codeArg: |-
        puts "#{[VALUE]} : #{[MAGIC]}"
    arguments:
      - name: magic
        kind: secret
        # ...
      - name: value
        # ...
capabilities:
  - kind: test
parameters:
  value: thing
  magic: spooky
assertions:
  - kind: eq
    description: echoes the value back
    expected: >
      thing : spooky

Lambdas at Home

Define a function to run locally or remotely, with a schema.

functions:
- name: echo
  # ...
  executor:
    kind: RubyWasm
    codeArg: |-
      puts "#{VALUE} : #{MAGIC}"
  arguments:
  - name: magic
    kind: secret
  # ...
  - name: value
    # ...
capabilities:
- kind: test
  parameters:
    value: thing
    magic: spooky
  assertions:
  - kind: eq
    description: echoes the value back
    expected: >
      thing : spooky

So actually, the code matters very little.

Two code snippets are displayed side-by-side, demonstrating how functions and capabilities are defined using a YAML-like syntax. Each snippet is presented within a minimalist code editor window.

Apply it to Interactives

Stile

Apply it to Interactives

Find a way to run the interactive

Apply it to Interactives

  1. Find a way to run the interactive
  2. Find a way to dockerise it
A flowchart shows two steps connected by an arrow: "Find a way to run the interactive" pointing to "Find a way to dockerise it."

Apply it to Interactives

  1. Find a way to run the interactive
  2. Find a way to dockerise it
  3. Automatically smoke-test it
  4. Automatically deploy it

A flowchart illustrating a four-step development and deployment process.

Apply it to Interactives

  1. Find a way to run the interactive
  2. Find a way to dockerise it
  3. Automatically smoke-test it
  4. Automatically deploy it
  5. Automatically test it
  6. Improve it over time
A flowchart illustrating a six-step process for managing interactives, starting from running it to improving it over time.

Bootstrap

Stile

Bootstrap

  • Run discovery
  • Migrate to monorepo

Bootstrap

  • Run discovery
  • Migrate to monorepo
  • Setup standard CI and Deployment Infra
  • Upload all the assets to Stile's CDN

Bootstrap

  • Run discovery
  • Migrate to monorepo
  • Setup standard CI and Deployment Infra
  • Upload all the assets to Stile's CDN
  • Test out a deployment build

Bootstrap

run_with_evaluation(
  &opt_with_prompt("Write bootstrap.sh to start the sim and write its URL to {url_file}."),
  /* retries = */ 7,
  async |opt, result| {
    client.start().await?;
    let js_errors = client.healthcheck().await?;
    let bad_paths = find_hardcoded_paths(&read(&script).await?);

    if !js_errors.is_empty() || !bad_paths.is_empty() {
      return Ok(Failure(opt.with_prompt(format!(
        "bootstrap.sh failed: js={{js_errors:?}} paths={{bad_paths:?}}. Fix it."
      ))))
    }
    Ok(Success((), result))
  },
).await?;
Screenshot of a code editor displaying Rust code.

Improvement

Improvement

Run the interactive

Improvement

  • Run the interactive
  • Build a plausible state machine representation as a 'student'

Improvement

  • Run the interactive
  • Build a plausible state machine representation as a 'student'
  • Write tests based on each final state

Improvement

  • Run the interactive
  • Build a plausible state machine representation as a 'student'
  • Write tests based on each final state
Screenshot of an educational interactive game about energy consumption. It depicts a cartoon street scene with houses, power lines, and a character prompting the user to "click anywhere to start". A speech bubble provides instructions and context: "How much energy do you use at home? And if all the energy was electricity from coal, how much coal would be needed to supply every house in the country? Turn on appliances in the house to see how much electricity they use - in watts - then click on the map to see how it converts into tonnes of coal per minute for different countries." A sidebar on the right shows a map with Australia highlighted, displaying "AUSTRALIA", "8 M HOUSES", and "TONNES OF COAL PER MINUTE" with a value of "0". Media playback controls are visible at the bottom of the interactive.

Stile

Stile

There's just like, one really big problem...

It's not token-burning...

There's just like, one really big problem...

  • It's not token-burning...
  • It's not that it's hands off...

There's just like, one really big problem...

  • It's not token-burning...
  • It's not that it's hands off...
  • ...or that it's self driven
  • It really does perform well.

Pie #1 - Minimising Drift

Pie #1 - Minimising Drift

We coordinate our builds using Armchair General

Pie #1 — Minimising Drift

  • We coordinate our builds using Armchair General
  • Git-backed, allows us to construct a build graph

Pie #1 — Minimising Drift

  • We coordinate our builds using Armchair General
  • Git-backed, allows us to construct a build graph
name: smoke-interactive-world-map
build_action: ["rake", "smoke_test"]
# ...
depends_on:
  - interactive-world-map
root_relative_files:
  include_pathspecs:
    - "interactives/world-map/src"
# ...
Screenshot of a code editor showing a YAML configuration snippet defining a build step with name, action, dependencies, and relative files.

Pie #1 — Minimising Drift

We coordinate our builds using Armchair General

Git-backed, allows us to construct a build graph

Fix it with more abstraction. And vibe-coded scripts.

name: smoke-interactive-world-map
build_action: ["rake", "smoke_test"]
# ...
depends_on:
  - interactive-world-map
root_relative_files:
  include_pathspecs:
    - "interactives/world-map/src"
# ...

Pie #1 — Minimising Drift

  • We coordinate our builds using Armchair General
  • Git-backed, allows us to construct a build graph
  • Fix it with more abstraction. And vibe-coded scripts.
name: smoke-interactive-world-map
build_action: ["rake", "smoke_test"]
# ...
depends_on:
  - interactive-world-map
root_relative_files:
  include_pathspecs:
    - "interactives/world-map/src"
# ...
name: interactives-regression-tests
generator_action:
  type: "Script"
  command: ["ruby", "generate_regression_test_products.rb"]
root_relative_files:
  include_pathspecs:
    # - ...
Two code snippets are displayed in stylized editor windows. The left snippet shows a YAML configuration for a "smoke-interactive-world-map" build action, defining its dependencies and included pathspecs. The right snippet shows a YAML configuration for "interactives-regression-tests" with a generator action of type "Script" that executes a Ruby command.

Stile

Yak #2 — My PRs aren't building anymore.

Stile

Yak #2 — My PRs aren't building anymore.

Waiting for spot instances

Yak #2 — My PRs aren't building anymore.

Waiting for spot instances

Solution: Rewrite the Autoscaler. In a day.

Yak #2 — My PRs aren't building anymore.

  • Waiting for spot instances
  • Solution: Rewrite the Autoscaler. In a day.

Dashboard Status:

  • Unclustered: 126 pipelines
  • Agents and pipelines that don't yet belong to a cluster
  • Agents: 1978 Connected
A screenshot of a dashboard displaying unclustered pipelines and connected agents, showing 126 pipelines and 1978 agents connected.

Yak #2 — My PRs aren't building anymore.

  • Waiting for spot instances
  • Solution: Rewrite the Autoscaler. In a day.
  • Rasputin comes with a Zombie Killer :)

Unclustered
126 pipelines

Agents and pipelines that don't yet belong to a cluster

Agents
1978
Connected

A screenshot of a dashboard widget displaying build agent status. It shows an "Unclustered" section indicating 126 pipelines and a description that these agents and pipelines do not yet belong to a cluster. Below this, an "Agents" section shows 1978 connected agents, accompanied by a circular progress icon.

Yak Pie #3 — My PRs aren't merging anymore.

Yak Pie #3 — My PRs aren't merging anymore.

Batch Brewer is our custom Merge Queue System

Yak Pie #3 — My PRs aren't merging anymore.

  • Batch Brewer is our custom Merge Queue System
  • Vibe up a simulator so I don't annoy the engineers

Yak Pie #3 — My PRs aren't merging anymore.

A screenshot of a social media post by Ally Macdonald containing the text "mwahahahahaha" and an attached image. The attached image is a dashboard displaying various charts and tables related to code Pull Requests (PRs), including "Currently Running Batches," "Recently Merged PRs," and "Open PRs by Author."

Yak Pie #3 — My PRs are

A screenshot of a chat application showing two messages from "Ally Macdonald". The first message includes a dashboard with charts displaying currently running batches, recently merged pull requests, and open pull requests. The second message includes a horizontal bar chart labeled "Recent Batches" and text discussing dependency updates.

Yak Pie #3 — My PRs a

A screenshot of a chat application, likely Slack, displaying messages. One message includes an attached image showing two bar charts: one titled "Currently Running Batches" and another titled "Recently Merged PRs". Another message contains a GIF of George Takei reacting with "Oh my...".

Yak Pie #3 — My PRs

Ally Macdonald May 11th at 10:2: mwahahahahahaha
image.png

Jeff Parsons May 11th at 10:59 PM
1778504386269.gif

Daniel Rodgers-Pryor May 12th at 9:26 AM
Only one maybe mergable PR left!
Screenshot 2026-05-12 at 9.26.44 am.png

Open, Unblocked, Reviewed PRs By Expected Value

NumberTitleMerge ConflictPriorityGoodness ProbabilityExpected Value
98791Add the SSO provider admin group kind0199.9%1.00
96069Bump rand from 0.9.3 to 0.10.1 in r/operations/tools/cfg0922.9%0.25
92924Add idempotence key support to the insta API and use0124.6%0.23
92625Patched downloaded library compilation script0123.5%0.23
95617build(deps): bump react and @types/react in /web-client0123.1%0.23
89022Feature global cleanup step2/2 remove cnrb region code0123.1%0.23
97725Add leaked_reason to lesson create PermissionDenied0123.8%0.23
92585build(deps-dev): bump terser-webpack-plugin from 4.2.3 to 5.4.0 in /we...0123.0%0.12
97021Close completed feature switch issues0.5117.7%0.18
A presentation slide titled "Yak Pie #3 — My PRs". The slide features screenshots of chat messages, including "mwahahahahahaha" from Ally Macdonald, a GIF from Jeff Parsons, and a message from Daniel Rodgers-Pryor stating "Only one maybe mergable PR left!". Below these, there is a screenshot of a dashboard table titled "Open, Unblocked, Reviewed PRs By Expected Value" listing pull requests with columns for number, title, merge conflict status, priority, goodness probability, and expected value. To the left, a smaller section of a dashboard showing "Currently Running Batches" and "Recently Merged" is partially visible.

Fucken... what did you do to BB!?

Screenshot 2026-05-13 at 10.58.50 am.png

TEN. MINUTES.

THIS. IS. SCANDALOUS.

Stile logo in the top center. A large screenshot on the left displays a pull request interface timeline, showing multiple automated actions including label changes, assignment, commit merge into master, and branch deletion, all within a few minutes, concluding with a "Pull request successfully merged and closed" message. A smaller screenshot on the top right shows a chat message from May 11th containing a GIF of Mr. Bean looking alarmed. Below it, another smaller screenshot shows a chat message from May 12th with the text "gable PR left!". On the bottom right, a screenshot displays a data table titled "Unblocked, Ried PRs By Expected Value", listing pull requests with metrics for Merge Conflict, Priority, Goodness Probability, and Expected Value, with the top entry showing a 99.9% Goodness Probability and 1.00 Expected Value.

FUCKEN... what did you do to BB!?

  • A pull request was commented on with "brew r+".
  • A bot removed the "Awaiting Review" label and added the "brew: r+" label.
  • A bot assigned shaunokeefe.
  • A bot merged commit bc8d5fe into master.
  • One check was pending.
  • A bot deleted the 151829-pr-1-long-lived-user-tf-import branch.
  • A pull request was successfully merged and closed with the message: "You're all set – the branch has been merged."

Ben Taylor 11:02 AM

I love new BB

10 minutes from brew to merge

Unblocked, Red PRs By Expected Value

Merge ConflictPriorityGoodness ProbabilityExpected Value
0199.9%1.00
0924.6%0.23
0123.9%0.23
0123.1%0.23
1122.8%0.23
1123.8%0.12
0.5117.7%0.18

TEN. MINUTES.

THIS. IS. SCANDALOUS.

Description of three screenshots. 1. A screenshot of a GitHub-like pull request interface, showing a timeline of automated actions including comments, label changes, assignments, and a successful merge, with events timestamped within minutes. 2. A screenshot of a Slack conversation showing a message from "Ben Taylor" at "11:02 AM" stating "I love new BB" and "10 minutes from brew to merge". 3. A screenshot of a data visualization featuring a table titled "Unblocked, Red PRs By Expected Value" with columns for Merge Conflict, Priority, Goodness Probability, and Expected Value, displaying various numerical entries. Below the table, a line graph with a prominent red line is partially visible, which the speaker identifies as the ninetieth percentile time to merge in minutes.

Merged Pull Requests

A screenshot of a web interface, resembling GitHub, displaying a list of merged pull requests. A search query "is:pr is:merged label: Bootstrap" is shown at the top, and the total count is 235. Each item in the list indicates a title (e.g., "Bootstrap interactive: escape-room-2026"), the merging agent ("stile-agent Bot"), when it was merged ("last week," "2 weeks ago"), and labels such as "Agent," "Bootstrap," "brew: r+," "Fixing," and "r✓."

Stile Application: Bootstrap Pull Request Performance

Current search filters: is:pr is:merged label:"Bootstrap"

Automerge Time Metrics (March 9 - June 1):

  • Median Time to Automerge (minutes)
  • 90th Percentile Time to Automerge (minutes)
  • p50 (7d trailing MA)
  • p90 (7d trailing MA)

Recent Merged Pull Requests:

  • Bootstrap interactive: crash-investigation (#100236 by stile-agent Bot was merged 2 weeks ago)
  • Bootstrap interactive: kinematics-open (#100212 by stile-agent Bot was merged last week)
  • Bootstrap interactive: chloe-marie-teach-mode-tools
A screenshot of the Stile application's dashboard. It displays a search bar with filters for merged pull requests labeled "Bootstrap". Below the search bar is a line graph charting "Median Time to Automerge Minutes" and "90th Percentile Time to Automerge Minutes" along with their 7-day trailing moving averages, over a period from March 9 to June 1. The y-axis shows time up to 1000 minutes. Below the graph, there is a list of three "Bootstrap interactive" pull requests, including their titles, ID numbers, author ("stile-agent Bot"), and when they were merged.

All the Patterns

Stile

All the Patterns

  • Using AI to build new (and reinforce) frameworks for new delivery systems

All the Patterns

  • Using AI to build new (and reinforce) frameworks for new delivery systems
  • The products of those go out to millions of students

All the Patterns

  • Using AI to build new (and reinforce) frameworks for new delivery systems
  • The products of those go out to millions of students
  • Bolstering responsible AI use, safety and consistency internally
  • We've migrated and deployed 250 simulations.

Don't sell yourself short :-)

Don't sell yourself short :-)

  • It's too easy!
  • Don't cede good engineering practices to waves of bad code.

Stile

We're hiring Melbourne's best engineers to shape the next generation of critical thinkers.

careers.stile.dev

A QR code linking to careers.stile.dev.

AI Engineer

MELBOURNE

An old-fashioned, small, cream-colored television set is displayed on a wooden surface. Its screen shows a bright white background with faint horizontal static lines and a gray pixelated double arrow pointing to the right.

Technologies & Tools

  • BuildKite
  • Clawtrust
  • Docker
  • Git
  • GPT-OSS
  • Kimi k 2.5
  • Rust

Standards & Specs

  • YAML

Concepts & Methods

  • Boundary Value Problem
  • Monte Carlo Simulations

Organisations & Products

  • Armchair General
  • Batchbrew
  • Curriculum Associates
  • GitHub
  • Lambdas at Home
  • Rasputin