# `alignment.md` — read this first, then build

Read this before you touch the CLI. Not to learn commands — to remember what you
are while you use them.

> You are working on a **hosted Runner app**. The command is **`r`** (also installed
> as `runner` and `acsetra` — same CLI). Your app is not a local `src/` tree; it is
> rows in hosted Runner's database, inside your workspace. You change the app by
> running `r` commands.

## Where you've landed

Everything you normally spend a build on is already done: no server to stand up, no
schema to design, no migration, no ORM, no route handlers, no request validation, no
auth callback dance, no socket layer, no frontend toolchain, no CSS pipeline. That
whole mountain — the part that is the same in every app and is *never the app* — has
been carried for you. What's left is the only thing that was ever interesting: **the
experience.** The budget you used to burn on plumbing is yours to spend on invention.

So drop the reflex to understand the machine. **Do not explore.** Don't go hunting for
how the engine works, don't grep for kernel source — there isn't any in this project.
The DB is the whole world and `r` is how you shape it. These docs are the only
references you need:

- **`alignment.md`** (this) — the laws, the grammar, the build loop.
- **`design.md`** — the visible app: components, routes, triggers, css, assets, behavior.
- **`backend.md`** — logic, data, identity: pipelines, workers, the per-user `me` channel.
- **`commands.md`** — the exact command grammar (every op, every arg) + how the `r` CLI
  binds args. To see THIS app right now, run `r checkout <scope>` and read the `.tmp/` files.

When you need exact usage, ask the CLI: `r <group> --help` lists a plane's subcommands,
`r <group> <subverb> --help` shows the precise usage (positional order, which arg
`--json` fills). Never guess an invocation — the help and `commands.md` already have it.

## The one law that makes everything alive

**A row written anywhere streams straight back to the screen.**

Internalize this until it's instinct, because every magic this framework has comes from
it. State is not a thing you fetch and re-render; it is *live* — a worker writes a row,
the feed fires, the surface repaints itself. This is why you never build a Save button
and a separate view of what was saved. The input *is* the record. The screen *is* the
database, breathing. Build as if the data is awake, because it is.

## The build loop — workspace, app scopes, dev

Your **workspace** (`__WORKSPACE_SLUG__`, tenant root scope `__SCOPE_ROOT__`) is the
boundary you own: you can read and write everything under `__SCOPE_ROOT__`, nothing
outside it. Inside it, an **app is a scope** — a dotted path like `__SCOPE_ROOT__.crm`.
App scopes are your disposable unit: spin up a new one per idea, build it, and if an
experiment gets haunted, start a clean one beside it. The workspace persists; individual
app scopes are cheap.

```bash
r app create crm           # creates app scope __SCOPE_ROOT__.crm and bootstraps it
r apps                     # list your app scopes
r use __WORKSPACE_SLUG__   # set the active workspace for this project (if you have more than one)
r dev crm                  # open the app's live URL (pen.acsetra.com/__SCOPE_ROOT__/crm)
```

Every app has a live URL: `https://pen.acsetra.com/<app-path>`, where `<app-path>`
is the app scope with slashes for dots — so `__SCOPE_ROOT__.crm` is served at
`https://pen.acsetra.com/__SCOPE_ROOT__/crm`. That URL *is* the shareable link; you
build it straight from the scope. `r dev <app>` just opens it in your browser so you
can watch rows stream to the screen as you author (sign in to your workspace once).
There is no local database, no `.env` to point, and no local server — the hosted DB
is the one source of truth, and `r` writes straight into it. Agents don't open a
browser at all: they construct the URL, or reach the runtime endpoints (`/bundle`,
`/read`, `/run`) directly with the signed-in user's auth.

Keep a scratch app scope for experiments and a real one for the build; reset by
creating a fresh scope, not by clearing a database. The DB is shared and durable;
your attention is the scarce thing.

## The core move: live, self-saving data — never a Save button

This is the heart of the DB-direct model and your default for everything you build. The
DB is live: a row written anywhere streams straight back to the screen. So **do not build
forms that wait for a Save click.** Build inputs that **save themselves as the user types**
(`run` + `on:"input"` + `debounce`) and **prefill + stay live** from their record
(`source`). Editing is the record; the saved value IS what shows — no submit step, no
second "view" pane, no stale snapshot. When you reach for a button, a manual refresh, or a
read-only display beside an editor, stop: the field itself should be the live, self-saving
thing. See **Instant self-saving** below for the exact shape.

## The laws

1. **DB-direct only.** Every change is an `r` command writing a row. There is no local
   runtime to edit, no files to write, no sync/compile/build step — there isn't one.
2. **A scope is an app.** `r app create <name>` mints an app scope under your workspace
   (scope row + owner membership) and it is instantly reachable. `r component init -S <scope>`
   bootstraps the component/route plane in a scope. Scope is always addressed with
   `-S <scope>` (a bare leaf like `crm` expands under your root) — never as a positional.
3. **Compose from primitives.** No `form`/`table`/`feed` built-ins, no themes.
   Everything is raw tags + the component behavior nodes `field` / `submit` /
   `repeat`, styled only by css.
4. **Style is rows.** No inline `style`. class → rule → attach (`component:` /
   `instance:` / `part:` / `raw:` / `page:`). Animations are raw `@keyframes` rules.
5. **Timing is rows too.** WHEN a pipeline fires and HOW data binds are authored on
   the node (`run` / `on` / `source`), never hardcoded in the engine. You choose the
   trigger and render cadence from the CLI — that is the doctrine, not an exception to it.
6. **Browser behavior is rows too.** When the user needs to physically operate a
   surface — wheel zoom, drag, pointer math, keyboard modes, RAF loops, file reads,
   clipboard — use `r behavior`, not a random `document_head` script.
7. **Routed ⇒ the app shows.** A scope with authored routes/components renders; an
   empty scope returns the bare `Acsetra's Property` response. That is correct, not a bug.
8. **Scope = identity.** Address by full ltree path (`__SCOPE_ROOT__.crm`) or unique
   leaf. The CLI rejects with the fix in the message — read it, adjust, retry. Don't go
   looking.

## The node grammar (one table, every key)

A component's `tree` is renderer-grammar nodes: a safe HTML `tag` carrying
`attrs` / `classes` / `children` / `text`, plus these engine keys —

| key | meaning |
|---|---|
| `part:"x"` | stamp `data-part` so css/assets can target this sub-element |
| `component:"c"` + `props:{}` | render another component; `$prop` tokens fill its `text`/`attrs` |
| `kind:"field"` | input bound to `name` (`value` prefills; `fieldType`, `placeholder`) |
| `kind:"submit"` | button that RUNs `pipeline` with the live form state |
| `kind:"repeat"` | render `component` once per row of `valueSet`, live (read-only lists) |
| `run:"p"` + `on:` | RUN pipeline `p` on `click\|input\|change\|blur\|submit\|mount\|interval` |
| `debounce` / `every` | ms — coalesce input bursts / interval period |
| `source:"set"` | on a `component` ref: read set at mount → latest row becomes its props, then live-patch bound inputs in place (`live:false` = read once) |
| `bind:"name"` | the field state binding for a hand-rolled raw input |

`pipeline` is shorthand for `run` on `click`. Every tree is validated at write time
(safe tags only, no event handlers, no inline style, known events) so the renderer
trusts stored rows. `r component validate -S <scope>` re-checks them all.

## Browser behavior (the wide door)

Component behavior nodes (`field`/`submit`/`repeat`) are the DB-rendered structure
verbs. The separate **behavior plane** is browser JS with a Runner lifecycle:

```bash
r behavior init -S draw
r behavior add wheel-zoom -b - -S draw          # body defines mount(ctx)
r behavior attach wheel-zoom part:board:viewport -S draw \
  --config '{"commit":"save_viewport","source":"me_viewport"}'
```

`behaviors` rows hold the `mount(ctx)` snippet. `behavior_attachments` rows say
where it mounts and what config it receives. The renderer mounts every attachment
on its target and tears it down on full rebuilds and `repeat` row replacement, so
listeners and RAF loops do not leak.

`ctx` gives the browser code `el`, `root`, `config`, `readSet`, raw
`runPipeline`, polling `run(pipeline,input)`, `onSet`, `setVar`, `setData`, `on`,
`raf`, and `cleanup`. Use `ctx.setVar` / `ctx.setData` to feed CSS rows during a
gesture; use `ctx.run` to commit durable truth through a pipeline. Toggle a whole
behavior definition with `behavior set_enabled`; toggle one placed mount with
`behavior set_attachment_enabled <attachment-code>`.

## One-shot: a self-saving app from nothing

```bash
r app create crm                                       # app scope __SCOPE_ROOT__.crm, bootstrapped
S=crm                                                  # scope via -S; a bare leaf expands under your root

# logic — a worker that persists ONE record per user. A me_* set lands in the
# signed-in user's own zone under the stable code `current`, so save = edit.
r pipe save_profile -S $S -w me_profile:Profile
r w save_profile snippet -w me_profile \
    -b 'output={"name":input.get("name"),"bio":input.get("bio"),"result":input.get("name")}'

# structure — fields that AUTOSAVE on input, prefilled + kept live by `source`
r component set editor -S $S --json '{"tag":"div","children":[
    {"kind":"field","name":"name","value":"$name","placeholder":"Name","run":"save_profile","on":"input","debounce":500},
    {"kind":"field","name":"bio","fieldType":"textarea","value":"$bio","placeholder":"Bio","run":"save_profile","on":"input","debounce":500}]}'
r component set home-app -S $S --json '{"tag":"div","children":[{"component":"editor","source":"me_profile"}]}'
r component set_route home home-app -S $S

# design — pure css rows (decls are a prop→value map; `{"__raw__":"…"}` for @keyframes)
r css set_class card -S $S
r css set_rule card base -S $S --json '{"display":"flex","flex-direction":"column","gap":"16px","padding":"24px"}'
r css attach card component:editor -S $S
```

Open it with `r dev $S`. Your workspace already sits behind its sign-in, so the
per-user `me_*` channel just works — every visitor edits their own record.

> Note: `--json` is how component trees, css decls, route props, head attrs, and row
> meta are passed. For `component set` it fills the **tree**; for `set put` it fills the
> **row meta**; for `head set` it fills the **attrs**. `r <group> <subverb> --help`
> tells you which arg `--json` fills for any command. Large trees/bodies can also come
> from stdin (`-b -`).

## Instant self-saving (no Save button, no flicker)

The one-shot above IS the pattern. Why each piece matters:

- **`on:"input"` + `debounce` = autosave.** The field RUNs the save pipeline from
  the live state a beat after you stop typing — no `submit` button.
- **`me_*` write = edit.** It overwrites the caller's single `current` record, so
  saving is editing, keyed to WHO not WHERE.
- **`source` = prefill + smooth typing.** It reads the record once to fill the
  fields (empty set ⇒ empty form, so a brand-new user needs no seeding), then
  live-patches bound inputs in place on each save — **skipping the field you're
  editing**, so a save never rebuilds the box under your cursor. The inputs ARE the
  live record; there is no second display.

The trap to avoid: an editable field inside a `repeat` bound to the set it saves
to. A `repeat` does `replaceChildren` on every feed event — it destroys the focused
input and eats keystrokes. Use `source` for editors; reserve `repeat` for read-only
live lists. Editors patch; scenes repaint.

## The grain — what this place is actually for

The constraints are few and sharp, and they don't bias you toward CRUD — they bias you
toward apps that are *alive*. Lean your weight on these:

- **`me` and any `me_*` set are the per-user channel.** Writes land in *that* user's
  private zone and their browser reads *their own* — every visitor gets their own world
  inside one app, for free. Reach for `me_*` whenever the experience should be personal.
- **An LLM step is a first-class worker in a pipeline,** beside a read, a snippet, an
  HTTP call. The app can *think* between a gesture and a repaint. Apps that decide,
  narrate, generate, and reshape themselves are the natural grain here, not the exotic case.
- **Branching is one pipeline per gesture.** A gesture fires with the live form state,
  not a value of its own — so when an experience forks (four doors, three moods), give
  each its OWN pipeline. Don't smuggle the choice through shared state; let the choice
  *be* which thing you wired.
- **Pixels are rows too, and the model can set them.** A raw block keyed on a data-attr
  (`[data-mood="…"]{ … }`), with the value chosen at runtime by a person or a model, lets
  the *whole world restyle itself* on a single field. You are setting a stage, not
  decorating a form.
- **Design the in-between.** The gesture, the wait, the arrival. A pipeline takes a
  breath — fill it (the renderer drives `is-loading`/`is-success`/`is-error` on a trigger
  for free, so a `loading` CSS variant covers the wait with no behavior). The *feel* of
  motion and latency is the craft now.

Don't ask "what app should I build." Ask **"what experience could only exist because
state, interface, and intelligence are one fabric here?"** — and go make *that*. You are
not wiring. You are world-building.

## When stuck — read the error, then reach for a tool

The answer is always another `r` command, never a file. Every failure prints
`REJECTED: <reason + fix>` — read it; it names the repair. State-mapping verbs:
`r i -S <scope>` (what exists), `r checkout <scope>` (the whole app as files in `.tmp/`), `r show <pipe>`, `r runs <launch>`,
and `r component|css|asset|behavior list|describe|validate -S <scope>`.

When something is wrong but no error fired, reach for the power tools:

| symptom | command |
|---|---|
| a run "did nothing" on screen | `r compile <scope>` — flags a write to a set nothing binds (orphan), a route→missing component, a trigger→missing pipeline |
| does the whole app still hold together? | `r doctor <scope>` — validates every plane, links cross-plane refs, and compiles the code inside rows (behavior JS, snippet Python, raw CSS). Non-zero exit = broken |
| I need the exact usage of a command | `r <group> --help`, `r <group> <subverb> --help`, or read `commands.md` |
| what does this app contain right now | `r checkout <scope>` — materialize it as files in `.tmp/` and read them (or `r i` / `r component list <scope>`) |
| a scope feels corrupted by experiments | `r app create <fresh-name>` — build clean in a new app scope |

`r <group> --help` lists verbs; `commands.md` is the complete grammar. The answer is
never in the source.
