# berry a self-modifiable agent harness on pi-durable and pi-codemode, with an aftercare frontend. ## layout - `api/`: `@berry/api`, what extensions are written against. `mod.ts` (server side), `web.ts` (renderers), `testing.ts` (one extension without a harness), `host.ts` (modules the app and extension bundles share). - `server/`: `berry.ts` is the harness (extension compiler, event folding, the builtin `berry` extension with codemode and its prompt sections); `codemode.ts`, `loader.ts` (reloads), `web.ts` (extension frontend builds), `http.ts`, `tree.ts`, `auth.ts`/`logins.ts`, `supervisor.ts` → `main.ts`. `dev.ts` is a faux model; `fixture.ts` is the test harness. - `extensions//`: `mod.ts`, optional `web.tsx`, tests. - `util/`: `@berry/util`, what tests share: `until`, `tempDir`, `onPath`, `PNG`; `dom.ts` has `withDom` (a happy-dom page as globals), `fill`/`press`, `viewContext`, and `fakeBerry` (a fake server for the app). `palette.ts` is plain data the app's bundles import too ( berry's terminal colors); extension modules may import any of it as a bare specifier. `web/testing.ts` signs the app's client in to one. - `web/`: the app. - `data/`: the live database. never touch it. ## commands - `deno check server/main.ts web/main.tsx extensions/*/mod.ts extensions/*/web.tsx` - `deno lint`, `deno fmt` - `deno task build` builds `web/` into `web/dist` ## you may be running inside berry - saving `extensions/` reloads that extension in place. `server/` and `api/` changes need a restart (the header's restart button, which interrupts calls in other conversations). an extension's reload copies only its own directory, so `@berry/api` changes need a restart too. - the server serves `web/dist` from disk: `deno task build` and a browser reload pick up app changes, with no restart. - don't run a second server on `data/`. a scratch instance takes `BERRY_DB`, `BERRY_PORT`, `BERRY_TOKEN`, and `BERRY_DEV_MODEL=1` (the `dev/echo` model, which spends no tokens). ## conventions - events are kept forever: a reducer must keep folding every event shape it has ever recorded. add new shapes rather than changing old ones. - an extension imports only its own directory's files and bare specifiers, so small helpers are repeated across extensions rather than shared. `web.tsx` never imports server-only modules. - harness behaviour is tested through `server/fixture.ts` (faux provider, memory storage), and extensions through `@berry/api/testing.ts`. tests are named for the behaviour they pin down. - tests share helpers through `@berry/util` (a bare specifier, so extension tests may use it too) rather than repeating them. a fixture that needs cleanup is `AsyncDisposable`, used with `await using`. - doc comments are one sentence on what a thing is or why it exists; line comments are lowercase and explain motivation only. - styles, the app's and extensions' alike, use the tokens in `web/style.css`'s `:root`: its colors, its type sizes (even pixels), and space in pixels on a 4px grid. each element's line height is its own, snapped to the grid, so a block takes more room with padding rather than a taller line. - dependency versions and policy live in `deno.json`. for pi package source, read `node_modules/@earendil-works//` (READMEs; the `.js.map` files carry `sourcesContent`). - version control is jj, colocated with git. don't commit unless asked. ## tests - test behavior, not CSS implementation. don't load stylesheets into DOM tests to assert selectors, declarations, dimensions, opacity, or animation timings: that duplicates the CSS and adds test churn. - check cosmetic changes in the browser. keep automated coverage for state, interactions, content, accessibility, and real rendering logic (such as ANSI color parsing), not style-change detectors. - a test earns its place by catching a regression nothing else would. don't pin exact copy, markup, schemas, or storage layouts; don't loop over inputs that take the same path; don't retest what a dependency guarantees (such as pi-durable persisting a document), or what another layer's test already covers.