# @lotics/cli — migration notes

What an app author has to DO when a release changes the shape of a project the CLI owns. Every
other contract is `docs/cli_reference.md`; this file is the one a reader opens once, because
something already on disk no longer matches what the CLI writes.

## Apps built from a plan are JSON

`lotics app create --from <model.json>#<app>` used to emit ~30 TSX files per app — `src/App.tsx`, a
screen per plan entry, the record each row opened, a dialog per create, `src/screens/cells.ts` — and
`lotics app regenerate` folded a later generation into them through a three-way merge over a base
recorded in `.lotics/generated/files/`.

It now writes **`app.json`**: the bound plan, whole. Beside it, a five-line `src/main.tsx` that
mounts `@lotics/app-runtime` over the spec, `src/components/index.ts` seeded empty, and the
`src/workflows/<alias>.ts` bodies, unchanged. `@lotics/app-runtime` draws the spec, so a kit
correction reaches the app with its next `npm install` rather than with a regeneration — which is
the whole point of the change.

**A TSX app keeps working.** It never depended on the generator at run time, and nothing in this
release touches a project that has no `app.json`. What it loses is the fold: `app regenerate` no
longer writes screens, so an app built before this release has two ways forward.

### Moving a generated app to the JSON form

1. `lotics app regenerate` in the app directory. It writes `app.json`, `src/main.tsx`,
   `src/components/index.ts` and the workflow bodies, and leaves everything else where it is.
2. Delete what the generator no longer emits — `src/App.tsx`, `src/screens/`, and
   `.lotics/generated/files/` (the merge base; the alias record in
   `.lotics/generated/manifest.json` STAYS, and is what tells the next run which aliases were the
   generator's). Anything of your own that lived under `src/screens/` moves to `src/components/`
   and is registered there.
3. `npm install @lotics/app-runtime`, then `lotics app check` and `lotics app deploy`.

Keeping the TSX instead is also a decision the CLI honours: delete `package.json#lotics.plan` and
the app is a hand-written project like any other. `app regenerate` then refuses, which is the
correct answer for a tree nothing generates.

### What changed in `app regenerate`

- **No three-way merge, and no conflict markers.** The generator owns every file it emits.
  `app.json` is derived whole; a workflow body is rewritten and what it replaced is parked in
  `.lotics/regenerate-dropped.patch`, file by file.
- **`src/components/` is the one exception** — seeded where it is absent, named back where you have
  changed it, never rewritten.
- **`.lotics/generated/files/` is gone.** Only the alias record remains. A tree still holding those
  `.base` copies is harmless; delete it.
- The summary counts `written / kept / deleted` rather than `written / merged / conflicted / kept /
  deleted`, and `lotics workspace build`'s per-app line counts files rewritten.

### What `lotics app check` now runs on a JSON app

Everything it ran before, plus the spec itself: a surface reading a column its own query never
projects, a read no alias declares, an act running a workflow nothing declares, a create sending an
input its body has no branch for, and a component the spec names that `src/components/` does not
export. A JSON app has no TSX for a compiler to refuse, so every mistake the typecheck used to
catch is caught there instead.
