Skip to content
dereksantosPublic

About

A protocol for building JavaScript apps that agents can author, verify, and reproduce — plus a tiny reference implementation in a single file.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Latest commit

 

History

15 Commits

Folders and files

Repository files navigation

leanjs

A protocol for building JavaScript apps that agents can author, verify, and reproduce — plus a tiny reference implementation in a single file.

  • Zero dependencies. Zero build step. Native ESM. Copy lean.js into your repo.
  • Schemas, components, adapters, workflows, verify. Five primitives. Nothing else.
  • Workflows + tokens = deterministic, reproducible verification.
  • Designed to fit in an agent's context window so the whole framework can be held in working memory while writing code.

Read SPEC.md for the protocol. Read AGENTS.md if you (or your agent) are writing apps in it. Read lean.js to see the whole implementation in a sitting.

Quickstart

Run the bundled examples through the verifier:

node bin/verify.mjs

Run one example:

node bin/verify.mjs counter

Run one workflow with custom tokens:

node bin/verify.mjs user-profile mounts-and-shows-name --tokens '{"user":{"seed":42}}'

Run the conformance suite (the contract any implementation must pass):

node bin/verify.mjs --conformance

Generate human-viewable snapshots of every workflow (synthetic data, per-step IR, action transcript — one HTML page per workflow plus an index):

node bin/snapshot.mjs
open snapshots/index.html

Run workflows in a real headless Chrome (no npm; uses your system Chrome/Chromium/Edge/Brave). Catches handler-wiring, event-bubbling, boolean-attribute, and other real-DOM-only bugs:

node tools/dom-verify.mjs                # all examples
node tools/dom-verify.mjs triage         # one example
node tools/dom-verify.mjs --only-dom     # only DOM-marked workflows

See AGENT_LOOP.md for the full iteration pattern an agent (or human) uses to drive an app from in-progress to ready.

The shape

import { string, email, schema, component, synthetic, wire, h,
         workflow, mount, action, expect, verify } from './lean.js';

const User = schema({ id: string(), name: string(), email: email() });

const UserCard = component({
  name: 'UserCard',
  needs: { user: User },
  actions: { rename: schema({ name: string() }) },
  on: { rename: async ({ payload, state, adapters }) =>
    adapters.user.methods.update(state.user.id, { name: payload.name }) },
  render: ({ user, dispatch }) =>
    h('article', null,
      h('h2', null, user.name),
      h('button', { onClick: () => dispatch('rename', { name: 'New' }) }, 'rename')),
});

const app = wire({
  components: { UserCard },
  adapters: { user: synthetic(User) }, // no backend needed
  mode: 'synthetic',
});

const wf = workflow('rename-flow', [
  mount('UserCard', { user: { adapter: 'user', method: 'get', args: ['u-1'] } }),
  action('rename', { name: 'Ada' }),
  expect(({ state }) => state.user.name === 'Ada'),
]);

await verify(wf, { user: { seed: 7 } }, { app });
// → { pass: true, reproduce: "node bin/verify.mjs ... --tokens '...'" }

Why

Most JS frameworks were designed when humans were the only authors. Agents have different ergonomics:

  • They benefit from small, regular surfaces that fit in context.
  • They are good at enumerating scenarios and bad at constructing fixtures. So scenarios should be tokens, not code.
  • They need to verify without backend access. Schemas + synthetic adapters give that for free.
  • They benefit from a zero-build, zero-dep loop where what they read is what runs and dependencies aren't a supply-chain hazard.

LeanJS is one shape that takes those constraints seriously.

Layout

SPEC.md             the protocol (normative)
AGENTS.md           how an agent should write apps in it
AGENT_LOOP.md       the iteration pattern for going from in-progress → ready
lean.js             single-file reference implementation, zero-dep
bin/verify.mjs      CLI: workflows + conformance (no browser, fast)
bin/snapshot.mjs    CLI: render workflows as HTML for human inspection
tools/              dev-time verification (uses system Chrome via CDP, no npm)
  chrome.mjs        locate Chrome/Chromium/Edge/Brave binary
  cdp.mjs           minimal Chrome DevTools Protocol client
  dom-verify.mjs    CLI: run workflows in a real headless Chrome
examples/           counter, user-profile, todo-list, triage, github-indexer
conformance/        cases any implementation must pass

Live example

examples/github-indexer/ is a realistic frontend app built on the protocol: a read-only GitHub public repo indexer with three views (new, popular, search), real fetch-backed adapter, URL routing, loading and error states. Tests run against a synthetic adapter (zero network); the browser runs the same component against the real GitHub API:

python3 -m http.server 8000
# open http://localhost:8000/examples/github-indexer/index.html

The bootstrap HTML is the membrane — the only file in the example that touches window, history, or location. The component is pure. This pattern is how LeanJS deliberately avoids useEffect-style escape hatches: browser-event subscriptions (popstate, polling, online/offline, resize) live in the bootstrap and call app.dispatch(inst, ...) to drive the framework.

Status

v0.2 — render context gains loading and errors; adapter exceptions during prop resolution surface via errors rather than halting the workflow (see SPEC.md § 10.1). The protocol and reference impl are complete enough that every example workflow, conformance case, and real-browser DOM test passes. The repo started in 2014 as a data-bind template library; that codebase has been retired (see git history) in favor of this schema-first, agent-authorable redesign.

About

A protocol for building JavaScript apps that agents can author, verify, and reproduce — plus a tiny reference implementation in a single file.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages