# Cut of the rewrite into frontend-v3: how to repeat it

Built from the dry run of 6 October 2026 (`REWRITE-DRY-RUN-LOG.md`, section 8 of `REWRITE-INTEGRATION.md`). The cut is done as a **vendor import plus an integration commit**, so a later snapshot of the rewrite can be merged in without redoing the integration work.

## The three branches

| Branch | Content | Rule |
|---|---|---|
| `cut-prep/vendor-s0` | The pristine mapped copy of rewrite snapshot S0, made by `import-rewrite.py`. Nothing else. | Only the script commits here. |
| `cut-prep/integration` | `vendor-s0` plus **one integration commit**: shell, session login, design tokens, routes, images, navigation, tests (the dry-run tree). | This is the branch that later becomes the cut. Nobody develops on it before the freeze. |
| `dry-run/rewrite-cut` | The dry run itself (throwaway, for reference). | Never merged. |

## Repeating the import with a newer snapshot (for example Bolt's final state at the freeze)

1. Make sure the rewrite snapshot is what you want (`origin/main` of the rewrite, plus any unmerged branch you need, merged in a detached worktree).
2. In a worktree of `cut-prep/vendor-s0`:
   `python tools/rewrite-cut/import-rewrite.py --rewrite <snapshot> --target <worktree>/frontend-v3`
   Read its output: **undecided collisions** (add a rule to the script and rerun), **files removed** since the last import, **shell files to port by hand** (the rewrite changed a file that frontend-v3 keeps, such as `router/index.ts`, `stores/auth.ts`, `App.vue`), **missing dependencies**.
3. Commit on `cut-prep/vendor-s0` ("vendor: rewrite snapshot S1").
4. In a worktree of `cut-prep/integration`: `git merge cut-prep/vendor-s0`. Git applies the changes between S0 and S1 to the files we edited. Expect conflicts only where both sides changed the same lines (in the dry run: `mappers.ts`, `HomeView.vue`).
5. Port the shell files the script listed, run `npm install` (regenerates `package-lock.json`; do not merge that file), then the checks below.

`frontend-v3/.rewrite-import-manifest` records what was copied and a hash of each rewrite file, which is how the script knows what to delete and what changed. Do not edit it by hand.

## Line endings

frontend-v3 and the rewrite store a mix of CRLF and LF files. The script therefore keeps the line-ending style of a file that already exists in frontend-v3, and its hashes ignore line endings. An editor flipping a file between CRLF and LF in the rewrite (Bolt's branch `raster-paging-FE` did this to `PollDetailView.vue`, 8,665 changed lines for a small fix) shows up as no change at all. No `.gitattributes` or other change in the rewrite repository is needed.

## Tested re-import (6 Oct 2026)

A fake second snapshot (CRLF/LF flips on two files, a one-line change in three files, a new file, a deleted spec, a change in a shell file) was imported onto the vendor branch and merged into the integration branch. Result: the flips produced no diff; the real changes were 1 to 2 lines each; the new file and the deletion merged cleanly; `router/index.ts` was reported for hand porting; our edits survived; **three conflicts**, all where the change was next to one of our edits (`mappers.ts`, `HomeView.vue`) or in a file we deleted (`LoginView.vue`: keep it deleted). Expect the same kind of conflicts at the freeze.

## Real re-import: Bolt's final state (7 Oct 2026)

Snapshot S1 is `bolt-last` (`0cc50e8`, 7 Oct 2026 10:29, tagged in the rewrite repository). Bolt's two open branches were obsolete (the dialog fix is superseded by `finishSubmitAs`; the copy-link buttons and the CSS line are already on `main`), so S1 is exactly the tag. Imported onto `cut-prep/vendor-s1`, merged into `cut-prep/integration`.
- **The script found one gap:** Bolt's new views refer to `/kulibri-logo.png` and `@2x`, static files in the rewrite's `public/` folder, which the script did not copy (8 test files failed with "Failed to resolve import"). It now copies the `public/` files that the source refers to by absolute path.
- **Shell files:** only `i18n/index.ts` changed, and only its messages (regenerated automatically). Router, auth store, `main.ts`, `App.vue` and `links.ts` were untouched.
- **Conflicts: two.** `HomeView.vue` (Bolt rewrote the dashboard cards, so Git reported the whole file as one block; resolved by taking his version and re-applying our three image edits) and `UserMenu.vue` (his new menu item style; our "Klassische Ansicht" entry added in that style).
- **One new spec adapted:** Bolt's `userMenuLogout.spec.ts` tested the token logout; it now tests the session logout (two requests) with the same intent.
- **Result:** 1,326 tests passed, 3 skipped, 1 failed (the three-part classic link, route map A4); 0 type errors; `npm run build` passes.

## The rules the script applies (decided in the dry run)

- **The rewrite's file wins** for `components/WysiwygEditor.vue`, `composables/usePollSync.ts`, `composables/useTheme.ts`, `mappers.ts`, `pollKeyStore.ts`, `types.ts`, `index.css`, `tailwind.config.js` and `__tests__/mappers.spec.ts`. (`useTheme.ts` is switched back to frontend-v3's version in the integration commit: it guards blocked storage, the rewrite's does not.)
- **frontend-v3's file stays** (the shell) for `App.vue`, `main.ts`, `router/index.ts`, `stores/auth.ts`, `i18n/index.ts`, `links.ts`, `utils/sanitize.ts` and two specs.
- **Moved on the way:** the rewrite's `api.ts` replaces `api/endpoints.ts` (imports adjusted); the rewrite's `i18n/index.ts` becomes `i18n/rewriteMessages.ts`; the rewrite's `__tests__/http.spec.ts` becomes `rwHttp.spec.ts`; frontend-v3's `__tests__/fixtures.ts` becomes `fixturesV3.ts` to make room.

## What the integration commit contains (hand work, from the dry run)

Details with reasons are in `REWRITE-DRY-RUN-LOG.md`. In short:
- `package.json`: add `qrcode.vue` and `xlsx`.
- Router: the rewrite's views behind frontend-v3's route names, `meta.ownShell` on the routes whose views bring their own header, the `login` route handed over to classic, the handover set extended.
- Session: `api/http.ts` gets `requestPublic`, `siteRoot`, silent mode and the empty-body fix; `stores/auth.ts` keeps the session store plus `refreshUser`, `updateUser`, `changePassword`; the login screens, their composables and specs are removed.
- Design: the rewrite's CSS and Tailwind config are the base; frontend-v3's header tokens appended; frontend-v3's 10 files moved from the `k-*` palette to the rewrite's tokens.
- i18n: `i18n/index.ts` deep-merges `rewriteMessages.ts` under its JSON, fallback `['en', 'de']`.
- Images: same-origin `resolveAssetUrl` (idempotent), previews on dashboard cards with a fallback.
- Navigation: one header per page; `useClassicSwitch` shared by both menus; the rewrite menu's dashboard entry opens the dashboard route.
- Guards: two entries in `formFieldsGuard`, one in `architecture.spec`; four account-deletion tests skipped until rewritten for the session.
- Specs: `integrated.spec.ts`, `classicSwitch.spec.ts`; `setToken` calls removed.

## Checks after an import or a merge

Inside `frontend-v3`: `npm install`, `npx vitest run`, `npx vue-tsc -b`, `npx vite build`. State of `cut-prep/integration` (6 Oct 2026, evening): **1,285 tests passed, 3 skipped, 1 failed** (the three-part classic link in `router.spec`, which is the route map, A4); **0 type errors**; `npm run build` (type check and bundle) passes in about 6 s. The 3 skipped tests are the live spec against the test server.
Then a browser check with a real session on `http://localhost:8000` (not `127.0.0.1`, the session cookie domain is `localhost`) and Xdebug off (`XDEBUG_MODE=off php artisan serve --port=8000`): the dashboard, a poll as owner and as visitor, editor, share, membership, `?classic=1`, phone width. Look for: one header and one user menu per page, no request to another host, no dashboard image above about 200 kB.
