For agents, on top of README.md, which they read first.
- Only the Worker talks to Jev, through
jev-clientonjev-worker's ports. Do not add a second Jev client or a retry loop here. Anything missing belongs in~/jevcrates, and this repo moves its submodule pin (the user, 2026-10-02: move shared functionality to jevcrates and depend on it). - The rules decide what happens to a query (
packages/rules,RULES), anddecideinapps/lmjtfy/src/lib.rsonly carries out whatNetwork::nextsays. A new step is a new fact and a rule, not anifin the Worker. The diagram is drawn from the same network, so it cannot show rules other than the ones that run. - Jev facts are asked for together.
Network::nextreturns every Jev fact a live rule is waiting on, and they go out as one request (the user, 2026-10-02: "firing a single request with N questions to backfill"). Do not ask for one in a request of its own. - The LLM is given only the tools the rules asked for (
llm::requestwithwants), and a question of any other kind it writes is not sent (llm::takes). Jev has already answered the other readings itself; a second answer to one of them from the LLM's wording disagrees with the first, as it did on 2026-10-02. - Jev answers; the LLM only writes the question. Never show the LLM's own text as an answer, and never have it answer when it makes no tool call.
- The tool call panels show the bodies that crossed the wire, indented and
coloured for reading (the user, 2026-10-02). Printing may add whitespace and
nothing else: no reordered keys, no dropped or summarised fields.
view's test parses the printed JSON back and compares it to the raw body, andask's tests hold the body shown equal to the body sent. /asksends the whole transcript in every event. Keep it that way: the browser has no state to get out of step with.- The same request is never sent to the same model twice (the user,
2026-10-02: "never send the same exact shape to the same
model, ever"), unless a visitor presses ↻ on it (the owner, later the
same day: "a button to bypass cache for a request"). Every Jev and LLM call
goes through
archive::call(apps/lmjtfy/src/archive.rs), which returns the kept response or makes the call once.Pick::Freshis the only way to send a kept request again, and only$pinsfrom the page sets it: never add another path that does. Every response is kept, as a numbered version, and does not expire; stepping through versions (Pick::Version) sends nothing, and neither does any call after the one stepped (KeptOnly). A new call site that reaches Jev or Workers AI any other way breaks the rule, and is also unmetered public spend: the archive is where the budget is held. - The site shows questions and answers and nothing about who asked. No page, feed, toast or preview may show a visitor's address, browser id, network or exact place (the online list's city and country is the one thing shown, the owner's ruling of 2026-10-02).
- The archive keeps everything, for the owner alone (the owner,
2026-10-03: "anywhere in the app where we are dropping data we should
plug", and of visitors, "Everything, linked"). Every request worth keeping
is a row of
events(packages/archive/src/event.rs): the question, how it ended, the address, the browser's id, the user agent, and Cloudflare's network and place. This reverses the rulings of 2026-10-02 (no address, nothing linking one browser's questions). Do not write that the site keeps nothing about visitors; chapter 2, "What is kept about visitors", is the true account, and a new thing that is known and thrown away is a bug. eventsis read only through the admin door (archive::ADMIN, the archive object's/adminpath), which only the owner's separate admin Worker reaches, by binding the object. This Worker must never send a request there or pass a visitor's request to the object, a socket upgrade on/liveaside: the object would read it as a message.- A question counts each browser once (
askers, the owner, 2026-10-02): the archive getsasker(id, question), a hash per browser per question, which is what counts it once. The hash is the key and says nothing to a reader; the browser's id is kept beside it (browser), as it is inevents, for the owner's backend. - What is listed is the rules' call (
Note::List, which needs Jev'sfitfact), unless the owner overrules it (asked.moderated, set through the admin door; the owner, 2026-10-03: "approve or unapprove, basic moderation"). Jev's verdict stays inlistedbeside it. Do not list a question by any other path, and read the feed withCOALESCE(moderated, listed). - A link preview reads the archive and asks nothing. Bots fetch every pasted link; a preview that made a call would spend the shared budget on them.
- The
wasm-bindgencrate is pinned to the nix CLI's exact version in the rootCargo.toml. Afternix flake update, move the pin andcargo update -p wasm-bindgentogether. - The dev server is pitchfork's, and starting it is the agent's job.
nix develop .#owner -c pitchfork start --local, then readpitchfork logs worker. Do not startwrangler devby hand beside it, and do not hand the user a command to run (the user, 2026-10-02). - Stop or restart it with pitchfork (
pitchfork stop --local,pitchfork restart worker), never withpkill -f wrangler:-fmatches the shell running the command and kills it (twice, 2026-10-02). - Two shells:
nix developfor anyone,nix develop .#ownerfor the owner's tools (lmjtfy-wrangler, lmjtfy-secret, lmjtfy-eval, pitchfork). Only the owner shell may usenix-pkgsornix-facts: Nix fetches a locked input only when an output uses it, so one reference from the default shell breaksnix developfor everyone who clones (they cannot read those repositories). - Do not export an
op://value from the devshell.op-env-runresolves every such value in the environment it is started from, with an account that cannot read the Cloudflare item, and refuses to start. That is why the eval's reference lives insidelmjtfy-eval. - Never pipe a value into
lmjtfy-wrangler. It runs op.exe before wrangler, and op.exe eats the stdin (an empty secret went live that way, 2026-10-02). Uselmjtfy-secret jev | account | analytics. - The neuron count is the account's, read from Cloudflare. Do not go back to counting only this Worker's calls: on 2026-10-02 the eval and local dev had spent 950 neurons the site's counter knew nothing about.
- Do not load-test the live site. Every answered ask is counted on the
public feed and in "So far" (2026-10-02: the agent's own rate-limit test put
"asked 67 times" on the home page). Load-test the dev server. On the live
site, ask once; to test the visitor limit there, post an empty
q, which counts towards the limit and touches nothing else. - After a deploy, check Jev with
/gateon text never sent before ({"q":"deploy check <time>"}): a missing or empty key still deploys cleanly and serves the page, and only a request that is really sent shows it. Never check with/ask: a question already kept sends nothing, so it tests nothing, and it adds an ask to the public count (2026-10-02: four such checks took one question from ×3 to ×7; MIGRATIONS step 4 undid it). To check the clone proxy,git ls-remote <site>/lmjtfy.git, which is not counted; a clone is. - The clone proxy serves
Repo::ALLand onlygit-upload-pack. Its token must stay read-only (Contents: read on those repositories), so a push is impossible at GitHub and not only at the routes. A new repository is a newRepovariant; never take the upstream from the request path..gitmodulesURLs stay relative, or a clone from the site points its submodule at private GitHub and fails. - The folders are a guide, chapter by chapter (the owner, 2026-10-02:
"read like the documentation subsite and like a tutorial flow", in the
spirit of why's (poignant) guide). Every folder's README is a chapter:
# Chapter N: <name>, <subtitle>, an opening that teaches the idea,> **Aside.**detours, aTry itagainst the live site orcargo test, the maintainers' reference, and a last line← Previous · Up · Next →in reading order (the prologue's table). A new folder gets its chapter and a CLAUDE.md, and the chapters after it are renumbered;view::code::guidefails the build on a folder without both, or a link that goes nowhere. The code pages' ◀ ▶ tabs follow those last lines, so the Next chain must be a depth-first walk (each folder before its subfolders, a subtree finished before its next sibling, every folder once, the last chapter with no Next);the_chapters_lead_on_depth_first_through_every_folderholds it. Playful, never at the expense of a true fact. - A deploy that people on the site should hear about carries a
Release-Note:trailer in its HEAD commit: one line, plain text, shown as a toast to every page from an earlier build when it reconnects (build.rs,LMJTFY_NOTE). Most deploys have none. - The site is
https://lmjtfy.fun, bare.lmjtfy.deizel.workers.dev(where it began) andwww.lmjtfy.funanswer only to redirect there for good (moved,ELSEWHERE). Write the bare address in docs, clone lines and Cargo lines. Do not redirect a request that is not a navigation: a page still open on the old address would lose its socket and its posts. - Deploy without asking (the user, 2026-10-02: "please deploy without
asking"). It is public and spends real money for every visitor, so deploy
only verified, committed work, and check the live site after.
Open work lives in the brain page
technology/artificial-intelligence/jev/lmjtfy.md.