Post

Pulse is our internal RSI tool: the self-improving automation we don't ship

Pulse is Lamplit Labs' internal recursive self-improvement tool for content automation. Not released, not a product - how the loop works and what it taught us.

Pulse is our internal RSI tool: the self-improving automation we don't ship

A disclosure before anything else, because every internal-tools post eventually gets misquoted: Pulse is Lamplit Labs’ internal RSI tool. It is not released, not open source, not a product, and there is no waitlist. RSI here means recursive self-improvement in the narrow, engineering sense: the system reads its own failures and proposes changes to its own operating layer - which a human then reviews, and which deterministic checks must accept before anything lands. There is no self-modifying code running unsupervised. There is a loop, and the loop has a fence around it.

We write about it occasionally - the automation evolution post walked through how it grew from a published hand-run checklist into a daemon that drafts and checks this blog - but readers keep asking the same questions. What does the loop actually look like? What is the AI allowed to touch? And why keep it internal? This post answers those, and shows a piece we have not shown before: how the failure-feedback half of the loop works.

The Pulse internal RSI loop

The loop, one turn at a time

One Pulse job is one turn of the loop:

  1. Plan. A scheduler proposes work - a missing check, a post on a topic the backlog voted up, a defect a gate keeps catching. Nothing here is autonomous in the interesting sense; the backlog, the ballots and the daily caps are set by humans and reviewed in the open.
  2. Work. A coding agent (the same kind we write about in the AI SDLC series) executes one task in a throwaway clone with pinned tools, no credentials, and a budget of model calls.
  3. Verify. The project’s own checks run before anything is committed: tools/test.sh with its coverage, tag and link rules, then bundle exec jekyll build. A job whose check fails lands nothing - the runner refuses it, and the failure becomes input to the loop rather than a broken deploy.
  4. Review. A human reads the branch. Not skimmed, not rubber-stamped: the diff, the check output, and the agent’s own report.
  5. Learn. Every failure - a rejected branch, a flaky check, a job that burned its budget without committing - is classified and written back into the system: better task briefs, a new deterministic check, a record so the next agent does not repeat the mistake.

Step 5 is the “recursive” part, and it is deliberately the most boring step in the loop.

The failure-feedback half, up close

The diagram’s “review memory” box holds three kinds of records. The first is the lesson: when three separate jobs landed nothing because their final check failed after the commits, that pattern got written down as a failure record - “verify exit status on the merged result before finishing” - and every later worker reads it before starting. The check that failed did not change; the briefs changed, and the failure rate for that class went to zero. The system improved its own instructions, which is the safest form of self-improvement there is.

The second is the vote: suggestions for new checks or posts are proposed as small cards - one file, one variable, one hypothesis - and other workers vote on them. Only a card with a measured signal ever becomes a job. That is how the 13-check gauntlet in tools/test.sh grew: each check is a card that won a vote, not a grand design. The prompt injection defences post enumerates what that layered posture produced.

The third is the gate change, and it is the one we are most conservative about. When Pulse itself noticed that posts with tables render poorly in the site’s list layout, the loop did not get to ban tables. A human added a style check, a human set its threshold, and the loop merely enforces it thereafter. The AI proposes; the checks dispose; humans own the checks. That sentence is the entire security posture, and it is why the loop can run unattended without ever being unsupervised in the ways that matter.

Why it stays internal

Three reasons, none of them mystical:

  • It is tuned to one repository. The briefs, the check list, the voter conventions and the failure records are all about this blog’s toolchain. A general version would be a different, much larger product with a support burden we do not want.
  • Its value is the process, not the code. Everything durable about Pulse is already public in the posts it helps produce: gate everything, make failures cheap, add one deterministic check per defect class, keep the model inside a fence of scripts. You can build that tomorrow with a CI pipeline and a task queue; Pulse is just our instance of it.
  • Internal tools get honest feedback. Because Pulse only serves us, its evals are our real workflows, not a demo set. The fine-tuning pipeline and the supply-chain checks in this series exist because the loop needed them, and they are better for it.

If a future version ever became a product, that would be a separate announcement and a separate threat model. Today it is a very opinionated set of scripts, a daemon, and a paper trail - and that is enough.

This post is licensed under CC BY 4.0 by the author.