# TeXise production release checklist

This checklist is for releases of the browser-first TeXise application hosted at
`https://www.texise.com` behind Apache2.

## 1. Source placement and licensing

- Confirm the production repository root is exactly
  `/var/www/texise.com/public_html`.
- Confirm `LICENSE` remains AGPL-3.0-or-later and the published source corresponds
  to the deployed browser application.
- Review `THIRD_PARTY_NOTICES.md` after dependency changes.
- Ensure no Payhip product secret, entitlement private key, user AI key, Git token,
  or predefined licence value is present in the browser build or repository.
- Run:

  ```bash
  node scripts/texise-release-audit.mjs
  ```

## 2. Required repository checks

From `/var/www/texise.com/public_html`:

```bash
pnpm install --frozen-lockfile
pnpm lint:ci
pnpm test:ci
pnpm run build
```

Before a formal release/PR completion, also run the repository-required
`pnpm local-ci-check`/Playwright release checks described in `AGENTS.md`.

Do not publish when a required check is failing.

## 3. Build artifact contract

After `pnpm run build`, confirm:

```bash
test -f /var/www/texise.com/public_html/dist/index.html
test -f /var/www/texise.com/public_html/dist/manifest.webmanifest
test -f /var/www/texise.com/public_html/dist/texise-texlive-sw.js
test -d /var/www/texise.com/public_html/dist/assets
test -d /var/www/texise.com/public_html/dist/locales
test -d /var/www/texise.com/public_html/dist/mathlive-fonts
test -f /var/www/texise.com/public_html/dist/compiler/swiftlatex-r3-v1/swiftlatexpdftex.wasm
```

`packages/tooling/browser-entry/dist` remains the native Vite output used by
Cloudflare/desktop tooling. Apache must never serve that workspace directory or
the source root directly; it serves root `dist` only.

When a prior root build exists, confirm `dist.previous` holds the previous
static build after a new successful build.

## 4. R14.1 project-model gate

Before testing optional features, prove the primary TeXise journey is no longer
the inherited Markdown-note flow:

1. create a new Browser/OPFS project;
2. confirm `main.tex` and `figures/` are created automatically;
3. confirm there is no `main.tex.md`;
4. confirm the app navigates directly to `main.tex`;
5. confirm Source, Visual and PDF surfaces are available for that file;
6. create `chapter1.tex`, `references.bib`, `custom.sty` and `notes.md` and
   confirm every filename is preserved exactly;
7. confirm Project Home and the sidebar list the non-Markdown project files;
8. create an empty folder and confirm no `untitled-*.md` placeholder appears;
9. rename, move, duplicate and delete a `.tex` file and confirm its extension is
   preserved;
10. reload and confirm the project structure survives.

A release fails this gate if any primary New File action appends `.md` or if a
new blank project lands in the Markdown editor instead of the LaTeX editor.

## 5. Browser release workflows

Run the committed Playwright suite when required for the release and then use
`playwright-cli` against the release candidate. Exercise at least:

1. create a Browser/OPFS workspace;
2. create a Free project from the template catalogue;
3. import a normal LaTeX project ZIP and export it again;
4. reload and confirm browser project persistence;
5. compile with the bundled browser compiler and verify PDF + SyncTeX;
6. edit an equation with MathLive;
7. make a Visual edit and confirm the exact `.tex` mutation;
8. initialise/commit a browser Git repository;
9. run TeXise Doctor;
10. start/join a collaboration room in two browser contexts;
11. exercise Free local AI, Project Meaning and Local Project RAG without a licence; verify exact identifiers use deterministic tools, conceptual answers expose trusted clickable project evidence, neither generation nor embedding model downloads occur until explicitly requested, Meaning vectors stay browser-local across reopen, then activate a test Pro entitlement and exercise a cloud BYOK review flow;
12. create range, cursor/point, semantic-object and project comments in both Source and Visual modes; reply, resolve and reopen them, reload to verify local persistence, and confirm canonical `.tex` contains no TeXise review markup;
13. exercise Review → History: filter by author/file/type, select Yesterday / last Git commit / last local snapshot / a chosen commit/date, create a manual snapshot, accept multiple tracked changes and an AI-authored change, then confirm checkpoints exist while Git/source files remain free of review metadata;
13. switch offline after one successful online load and confirm the PWA shell reloads.

## 6. Firefox / browser-storage path

In a browser without `showDirectoryPicker`:

- create a Browser workspace;
- confirm OPFS/IndexedDB fallback works;
- inspect the browser-storage persistence/quota indicator;
- request persistent storage where available;
- import a project ZIP, edit it, reload, compile and export another ZIP;
- verify the exported ZIP contains all `.tex/.bib/.sty/.cls` files and binary
  PNG/SVG/EPS/PDF assets but no AI keys, licence entitlement, browser caches, local AI model/runtime caches or
  TeX Live cache.

## 7. Native-folder path

On a browser with File System Access support:

- open/create a local-folder workspace;
- confirm source/image writes appear directly in the selected directory;
- verify an external file modification is detected without overwriting unsaved
  browser edits;
- confirm a template refuses a non-empty target directory.

## 8. Production host

Before activation:

```bash
apache2ctl configtest
systemctl status texise
curl --fail http://127.0.0.1:3100/api/health
```

Confirm `/etc/texise/*` is preserved and permissioned correctly, including:

- `texise.env`
- `config.json`
- `license-keys`
- `entitlement-private.pem`
- `entitlement-public.pem`
- `entitlement-refresh.key`

The trusted Node API must listen only on `127.0.0.1` and Apache must proxy
`/api/*` to it.

Confirm systemd is using:

```text
WorkingDirectory=/var/www/texise.com/public_html/texise-data/runtime/current/server
ExecStart=/usr/bin/node /var/www/texise.com/public_html/texise-data/runtime/current/server/index.mjs
```

## 9. Apache/security checks

Confirm the active vhost contains:

```text
DocumentRoot /var/www/texise.com/public_html/dist
```

and does **not** use `/var/www/texise.com/public_html` as the DocumentRoot.

Against `https://www.texise.com` confirm:

- valid TLS certificate;
- HTTP redirects to HTTPS;
- HSTS on HTTPS;
- `X-Content-Type-Options: nosniff`;
- `Referrer-Policy: strict-origin-when-cross-origin`;
- `X-Frame-Options: SAMEORIGIN`;
- restrictive camera/microphone/geolocation/payment permissions policy;
- `.wasm` is served as `application/wasm`;
- `index.html`, manifest, and service worker are not long-lived cached;
- versioned assets/TeXLive/compiler/MathLive fonts/locales use immutable caching;
- an unknown SPA route such as `/__texise_spa_health__` returns the app shell.

## 10. Upgrade and rollback

Test the installer/upgrade against a staging host before production:

- source remains at `/var/www/texise.com/public_html` and is not replaced by
  a symlink;
- existing `/etc/texise/*` survives unchanged;
- `pnpm run build` produces the Apache-served root `dist`;
- the prior root browser build becomes `dist.previous`;
- no `/opt/texise` or `/var/www/app.texise.com/releases` tree is created;
- failed post-deploy health checks restore both `dist.previous` and the previous trusted-API runtime snapshot when available;
- `/api/health` and `/release.json` advertise the same release ID;
- authoritative `/collab-live` passes snapshot replay, document update, awareness and peer-departure certification; compatibility-only `/collab-signal` still passes its migration health check;
- `release/sbom.spdx.json`, `release/provenance.json`, and `release/SHA256SUMS` are present;
- `uninstall.sh` removes generated build/runtime integration but preserves the
  complete source tree;
- `uninstall.sh --purge` removes trusted config/data/logs but still preserves
  source code.

## 11. Post-deploy smoke

After deployment, repeat the browser persistence, compile/PDF/SyncTeX and Pro
activation smokes against `https://www.texise.com`. Inspect the browser console,
Apache logs, and `texise.service` logs for new errors before declaring the
release complete.

## R14.5 release certification

Run `pnpm run release:quality` on a connected clean runner. Do not tag a public release unless lint, unit tests, production build, static contract audit, Chromium E2E, and Firefox E2E all pass together.

## R14.8 MathLive stabilisation gate

In both Chromium and Firefox:

- open a `.tex` file containing inline and display math;
- switch to Visual and confirm equations render as read-only MathLive previews;
- click an editable equation and confirm the dedicated MathLive editor opens;
- change the equation and click **Cancel**; canonical `.tex` must remain byte-identical;
- reopen it, change the equation and click **Apply**; only the exact math body range may change and the original delimiter/environment must remain intact;
- repeat an equation edit after an ordinary Visual prose edit and confirm neither edit is lost;
- while the equation editor is open, change canonical Source and then attempt Apply; TeXise must reject the stale edit;
- confirm equations containing `\\label`, `\\tag`, `\\nonumber`, comments, or other structural directives remain source-only;
- confirm Escape cancels and Ctrl/Cmd+Enter applies without a focusout/change auto-commit.


## R14.9 usable Visual editor gate

In both Chromium and Firefox, use a realistic article rather than a one-line fixture:

- confirm plain paragraphs remain directly editable;
- confirm `\textbf`, `\textit`/`\emph`, `\underline`, and `\texttt` bodies render with visual formatting and edits change only their argument ranges;
- confirm `\url` and simple `\href` labels remain visually editable without rewriting their wrapper/target syntax;
- confirm an unsupported inline macro such as `\custommacro{LOCKED}` appears as a small protected inline LaTeX island while text before and after it remains editable;
- confirm `itemize` and `enumerate` render as real editable Visual lists and editing an item changes only the item body, not `\item` or environment markers;
- confirm citations, references, footnotes, and MathLive equations still retain their specialised source-backed nodes inside mixed paragraphs/list items;
- confirm an unsupported custom environment is protected as one Raw LaTeX block while adjacent paragraphs remain editable;
- switch back to Source and verify all untouched LaTeX is byte-preserved outside the edited source ranges.


## R14.10 integrated editor release-candidate gate

Do not certify R14.10 from isolated component tests. On a connected clean runner,
`pnpm run release:quality` must pass the complete journey in both Chromium and
Firefox:

- create a blank project and open `main.tex` directly;
- edit canonical Source, switch to Visual, edit ordinary prose and apply a MathLive equation change;
- switch Source ↔ Visual repeatedly and confirm the same Source editor instance and exact canonical text survive;
- initialize the real browser pdfLaTeX runtime, pass its package self-test, compile, and obtain a PDF;
- select and search real PDF.js text-layer content;
- use Source → PDF SyncTeX and **Alt-double-click** the PDF text layer for PDF → Source SyncTeX;
- reload the editor, verify the canonical source persists, then compile again from the fresh in-memory session;
- export the whole project ZIP and import it into a newly-created untouched blank project; generated bootstrap `main.tex` may be replaced, but any user-modified existing file must still block overwrite;
- compile the imported project successfully;
- run the release-only portability gate that exports the archive from Chromium, imports those exact bytes into a separate Firefox profile, and compiles there;
- fail certification on uncaught browser `pageerror`/fatal runtime exceptions;
- only after the frozen install, lint/type checks, unit tests, production build, audit, Chromium suite, Firefox suite and cross-browser portability pass may `dist/release/certification.json` be emitted and `release/SHA256SUMS` refreshed.

## R14.11 TeXise Visual UX gate

In both Chromium and Firefox:

- hover an editable Visual block and confirm the TeXise left `+` and drag grip appear;
- click `+` and confirm the Visual slash menu opens at the block; Alt-click `+` must target insertion above;
- type `/` while editing Visual content and confirm the same slash menu opens without inserting a literal slash into canonical LaTeX;
- insert Section, Subsection, Bullet list, Numbered list, Equation and Table blocks and verify each operation creates the expected canonical LaTeX structure;
- drag a whole Visual block above/below another block and verify its complete original source range is moved without reserializing untouched LaTeX;
- select editable Visual text and confirm the floating formatting toolbar exposes Bold, Italic, Underline, Code and Link;
- apply formatting and confirm only the mapped selected source range is wrapped (`\\textbf`, `\\emph`, `\\underline`, `\\texttt`, `\\href`);
- perform a Visual prose edit before a slash/drag/format action and confirm the structural action maps through the pending Visual edits rather than overwriting them;
- switch back to Source and verify all untouched syntax remains byte-preserved outside the intentional structural edit ranges.

## R14.12 P0 Visual correctness gate

Static checks and runtime certification are deliberately separate:

```bash
pnpm run texise:contract-audit
pnpm run release:quality
```

`texise:contract-audit` validates source/package/deployment invariants only. It is **not** browser/runtime certification. A production release is certified only when `release:quality` completes and writes `dist/release/certification.json` with `artifactKind: runtime-browser-certification`, `certificationLevel: production-browser`, and `status: passed`.

Before release, verify in both Chromium and Firefox:

- Type several characters continuously in Visual mode; one Ctrl/Cmd+Z restores the text from before that typing session and Ctrl/Cmd+Shift+Z restores it.
- A slash insertion, formatting operation, MathLive Apply, or block move remains a separate undo transaction from adjacent typing.
- Undo and redo can be invoked from either Source or Visual mode because both use the same canonical `.tex` history.
- Dragging a `section` moves the section heading plus all paragraphs/subsections until the next section/chapter.
- Dragging a `subsection` moves through nested subsubsections until the next subsection/section/chapter.
- Dropping a heading onto content inside its own subtree is rejected without changing source.
- The R14.12 Playwright P0 regression is part of the production Chromium/Firefox release suite.

## R14.13 Native TeXise Visual interaction gate

- Typing `/equ` in Visual keeps editor focus, filters the slash menu inline, and Enter inserts display math without persisting `/equ` in `.tex`.
- The left `+` invokes the same suggestion engine and supports Alt+click insert-above.
- `/citation` opens real project bibliography entries; no placeholder citation key is inserted.
- `/reference` lists labels discovered by the semantic index; no placeholder label is inserted.
- `/equation` opens MathLive immediately after structural insertion.
- Selecting text and choosing Link opens the floating link editor; no `window.prompt()` is used. Existing `\href` wrappers can be edited or removed losslessly.
- Mouse drag auto-scrolls near the Visual viewport edge and shows an exact before/after indicator. Touch/pen dragging works through pointer events on the same grip.
- `latex-visual-r14-13.e2e.ts` is part of the Chromium/Firefox production release suite.


## R14.13.1 Visual list startup hotfix gate

- Production startup must construct the LaTeX Visual ProseMirror schema without a non-generatable-node exception.
- `visual_list` must use a generatable content expression while parsed lists still contain concrete source-mapped `visual_list_item` nodes.
- Open a `.tex` project containing `itemize`/`enumerate`, switch to Visual, and verify no blank screen or schema exception occurs.

## R14.14 core recovery gate

- [ ] Switch `main.tex` and another `.tex` file repeatedly without refresh; the selected file content appears immediately.
- [ ] Switch through `.bib` and `.sty` source files without stale editor content.
- [ ] Edit ordinary prose in Visual mode and confirm the canonical `.tex` source changes.
- [ ] Type `/sec` in Visual and insert a section using the native TeXise suggestion engine.
- [ ] Insert/edit an equation without `Mathfield not mounted` or an app-level ErrorBoundary.
- [ ] pdfLaTeX compiles the real root directly; logs contain neither `__texise_synctex__.tex` nor `\synctex=1`.
- [ ] Official `full` compiler profile reports and compiles pdfLaTeX, XeLaTeX and LuaLaTeX.
- [ ] `pnpm run release:quality` passes Chromium and Firefox R14.14 recovery tests before certification is emitted.

## R14.15 split workspace and scroll-sync gate

- [ ] Open a compiled 10-page document and verify the global editor toolbar, Source/Visual toolbar, PDF toolbar, PDF search/status controls, and PDF footer stay fixed while only document panes scroll.
- [ ] Scrolling Source moves the continuous PDF viewport to the corresponding SyncTeX location without moving the browser page.
- [ ] Scrolling Visual moves the continuous PDF viewport using the Visual block nearest the viewport centre.
- [ ] Scrolling the PDF with **Editor follows PDF scroll** enabled reveals the corresponding location in the active Source or Visual surface without forcing a mode switch.
- [ ] Enable both scroll-sync directions and verify the feedback-loop guards prevent oscillation.
- [ ] Disable either direction independently and verify the corresponding pane stops following while the other direction still works.
- [ ] Confirm the PDF viewer renders a continuous page stack, keeps selectable/searchable PDF.js text layers, and virtualizes pages away from the viewport.
- [ ] Search a term on a later page and verify the matching page/result is scrolled into view and highlighted.
- [ ] Alt-double-click PDF text continues to perform an explicit PDF → Source jump.
- [ ] `latex-split-scroll-r14-15.e2e.ts` passes in both Chromium and Firefox as part of `pnpm run release:quality`.

## R14.20 integrated editor certification gate

R14.20 is the final editor-migration certification stage. A source/static audit alone does **not** certify this release. On a connected clean runner, `pnpm run release:quality` must complete the production build and the full Playwright matrix in **Microsoft Edge, Chromium, and Firefox** before `dist/release/certification.json` is emitted.

- [ ] Run 100 complete `main.tex → chapter.tex → style.sty → refs.bib → main.tex` cycles; the active filename and active contents must always match and no browser refresh may be required.
- [ ] Place the Source caret around line 500 and prove autosave, compile, project semantic refresh, file-tree refresh, Visual projection refresh, and passive PDF → Source scroll synchronisation do not change the caret.
- [ ] Toggle Soft Wrap On/Off repeatedly; wrapping must be viewport-only, the same CodeMirror `EditorView` must survive, and the caret must not move.
- [ ] Run Source ↔ Visual repeatedly and verify exact canonical text survives with no blank editor or stale projection.
- [ ] Exercise the required Source and Visual semantic command matrix: Bold, Italic, Underline, Section, Subsection, Itemize, Enumerate, Inline Math, Display Math/Equation, Figure, Table, Citation, Reference, Label, Footnote, and Link/Hyperlink.
- [ ] Verify Source and Visual use the shared TeXise MathLive path and MathLive failures remain locally recoverable.
- [ ] Compile with pdfLaTeX, XeLaTeX, and LuaLaTeX under the `full` compiler profile; verify PDF generation, PDF.js selection/search, Source → PDF SyncTeX, explicit Alt-double-click PDF → Source selection, and passive PDF scroll reveal without caret movement.
- [ ] Confirm `release-quality-report.json` records the three browser projects and certification is written only after every runtime gate succeeds.


## R14.21 production runtime certification and deployment gate

R14.21 turns the R14.20 browser matrix into the default/full production activation gate rather than leaving it as an optional pre-tag check.

- [ ] `node --test scripts/release-runtime-hardening.test.mjs` passes from the clean source archive without `node_modules` or `.git`.
- [ ] `node scripts/release-runtime-preflight.mjs` reports Node 22+, the pinned pnpm version and required system commands; if pnpm is missing, run `corepack enable` before retrying.
- [ ] Release-critical `custom-validation` and `test:ci` run without Bun or Git-worktree metadata.
- [ ] `pnpm run release:quality` provisions the full BusyTeX profile and completes lint/type, unit, production build, static audit, Edge, Chromium and Firefox.
- [ ] `dist/release/certification.json` has `status: passed`, `certificationLevel: production-browser`, and the same `releaseId` as `dist/release.json`.
- [ ] A default/full `scripts/install.sh` or `scripts/upgrade.sh` refuses activation when runtime certification is absent or mismatched.
- [ ] Post-deploy health verifies frontend/API/certification release pairing and serves `/release/certification.json`.
- [ ] `pnpm run release:deployment-smoke` passes against the deployed production origin and verifies CSP/HSTS, release identity, browser matrix and pdfLaTeX/XeLaTeX/LuaLaTeX.


## R14.28.12 scientific runtime certification gate

The normal release E2E matrix must run the zero-download scientific runtime
preflight in Edge/Chromium, Firefox and desktop WebKit. In the research terminal:

```text
runtime doctor
```

must report browser capabilities and Python/R/WASI compatibility while leaving
all three heavyweight runtimes in `not-loaded` state. On Chromium/Edge the
production Vite/Apache headers must yield `crossOriginIsolated === true` so the
Wasmer/WASIX path has its required SharedArrayBuffer boundary.

On a connected release runner, require the real external runtime gate with:

```bash
TEXISE_SCIENTIFIC_RUNTIME_LIVE=1 \
TEXISE_C_CPP_LIVE=1 \
pnpm run release:scientific-runtimes
```

This performs real Pyodide and webR execution, generates Python/R plot artifacts,
resets/reinitializes both runtimes, loads a certified WASI utility, and exercises
the pinned Wasmer/Clang C/C++ toolchain. A normal `pnpm run release:quality`
records the live scientific gate as `not-run` unless
`TEXISE_SCIENTIFIC_RUNTIME_LIVE=1` is supplied; certification metadata must not
claim those CDN-backed runtimes were executed when the opt-in gate did not run.

For runtime recovery without reloading the project use:

```text
runtime reset python
runtime reset r
runtime reset wasi
runtime reset all
```
