# TechLog UI migration baseline ## Source provenance - Source path: `/home/donghyeon/workspace/techlog-studio-frontend` - Inspected: 2026-08-15 (Asia/Seoul) - Git revision/status: unavailable. The supplied source directory is an exported checkout with no `.git` metadata; both `git rev-parse HEAD` and `git status --short` report that it is not a Git repository. The source path and the byte checksums below are the reproducible provenance available for this baseline. ## Approved copied assets | Source and target-relative path | SHA-256 | | --- | --- | | `public/favicon.svg` | `e6d2e59b7b5bbb0342e0fb496dfc262decbfe4426bbb7b047aec8d467d1dc6f7` | | `public/media/fetch-strategy-boundary.svg` | `b07926823ed77fc200f962a1f64a440e130cefa6bed31144b611612af9b02606` | Only these two SVGs are approved for this baseline. They must remain exact byte-for-byte copies of the source assets. The evidence key `fetch-strategy-boundary` resolves to `/media/fetch-strategy-boundary.svg` with dimensions `1080 × 420`, trigger label `Fetch Join과 Batch Fetch 비교 다이어그램 크게 보기`, and dialog label `Fetch Join과 Batch Fetch의 페이징 경계 확대`. ## Required dependency pins | Package | Exact version | | --- | --- | | `pretendard` | `1.3.9` | | `@fontsource/ibm-plex-mono` | `5.3.0` | | `unified` | `11.0.5` | | `remark-parse` | `11.0.0` | | `remark-gfm` | `4.0.1` | | `remark-directive` | `4.0.0` | No Next.js, Vinext, or Cloudflare package is part of the migration baseline. ## Expected route inventory | Layout | Route ID | Path | | --- | --- | --- | | PUBLIC | `TECH_LOG_HOME` | `/` | | PUBLIC | `TECH_LOG_EXPLORE` | `/explore` | | PUBLIC | `TECH_LOG_EXPLORE_KIND` | `/explore/:kind` | | PUBLIC | `TECH_LOG_CASE` | `/cases/:slug` | | PUBLIC | `TECH_LOG_REFERENCE` | `/references/:slug` | | PUBLIC | `TECH_LOG_QUESTION` | `/questions/:slug` | | PUBLIC | `TECH_LOG_TOPIC` | `/topics/:slug` | | PUBLIC | `TECH_LOG_PROJECTS` | `/projects` | | PUBLIC | `TECH_LOG_PROJECT` | `/projects/:slug` | | PUBLIC | `TECH_LOG_PROJECT_RECORDS` | `/projects/:slug/records` | | PUBLIC | `TECH_LOG_PROJECT_DECISIONS` | `/projects/:slug/decisions` | | PUBLIC | `TECH_LOG_PROJECT_ACTIVITY` | `/projects/:slug/activity` | | PUBLIC | `TECH_LOG_RELEASES` | `/releases` | | PUBLIC | `TECH_LOG_RELEASE` | `/releases/:version` | | PUBLIC | `TECH_LOG_PROFILE` | `/profile` | | PUBLIC | `TECH_LOG_SEARCH` | `/search` | | STUDIO | `TECH_LOG_STUDIO_HOME` | `/studio` | | STUDIO | `TECH_LOG_STUDIO_DOCUMENTS` | `/studio/documents` | | STUDIO | `TECH_LOG_STUDIO_DOCUMENT_NEW` | `/studio/documents/new` | | STUDIO | `TECH_LOG_STUDIO_DOCUMENT_EDIT` | `/studio/documents/:id/edit` | | STUDIO | `TECH_LOG_STUDIO_DOCUMENT_VALIDATION` | `/studio/documents/:id/validation` | | STUDIO | `TECH_LOG_STUDIO_DOCUMENT_PREVIEW` | `/studio/documents/:id/preview` | | STUDIO | `TECH_LOG_STUDIO_DOCUMENT_PUBLISH` | `/studio/documents/:id/publish` | | STUDIO | `TECH_LOG_STUDIO_PUBLICATIONS` | `/studio/publications` | | STUDIO | `TECH_LOG_STUDIO_PUBLICATION_PREVIEW` | `/studio/publications/:publicationEventId/preview` | | STUDIO | `TECH_LOG_STUDIO_NOT_FOUND` | `/studio/*` | | PUBLIC | `NOT_FOUND` | `*` | ## Source stylesheet inventory - `app/globals.css` → `presentation/styles/globals.css` — `901205054ee96fe15062aaef7ff39c701985fdece15b58f7656776d0b744e607` - `app/studio.css` → `presentation/styles/studio.css` — `d0d958baeb55b74796988d8c0967a7c62d211e595224e07912aa1f884e466fdd` - `app/studio-editor.css` → `presentation/styles/studio-editor.css` — `ae9a473192d24465021d021cd42a5a84f9bdf4c3af0664537b4e10006ca1f889` - `components/studio/workflow.module.css` → `presentation/styles/workflow.module.css` — `8eaa478a88ef4d16429c7f6a32bb33631acb47deef0b40838edd0a72748f124e` - `components/studio/publication-flow.module.css` → `presentation/styles/publication-flow.module.css` — `5b1fdebeb27248b5cebc700b12d15cf11fe70471a394c9dc643a98c4569e8674` All five source/target pairs passed `cmp -s` and have identical SHA-256 digests. Production parity testing corrected the provisional bootstrap assumption in the design: the target loads the byte-identical TechLog `globals.css`, including its first-byte `@import "tailwindcss";`, exactly once and does not load the starter `theme.css`. This reproduces the source cascade; the resulting browser comparison is pixel-identical. ## Source-to-target browser parity The source was copied to `/tmp/techlog-source-parity.I0CBK7` before build and runtime caches were created. The supplied source directory was used only for read-only file comparison; it was not edited. The temp-copy Vinext production server and the target Vite preview were captured by one Playwright Chromium instance with two fresh contexts under identical conditions: - `ko-KR`, `Asia/Seoul`, light color scheme, reduced motion, device scale 1, service workers blocked, and a fixed `2026-08-14T01:00:00.000Z` clock; - 1000-pixel viewport height, full-page screenshots, `document.fonts.ready`, Pretendard/IBM Plex font checks, zero-duration animation/transition/caret; - no screenshot masks; exact RGBA pixel comparison plus product-subtree tag/class/text/ARIA projection and console/request failure comparison. | Evidence group | Cases | | --- | ---: | | 27 canonical routes at 360 and 1440 pixels | 54 | | Public home breakpoint transitions | 12 | | Studio screen/state fixtures | 19 | | Ten unknown Public dynamic shapes at 360 and 1440 pixels | 20 | | Search/menu/preview/dialog/publication interactions | 7 | | **Total** | **112** | Result: 112/112 passed, zero failed, zero different pixels, all DOM/class/text/ ARIA projections equal, and zero unexplained source or target console/request errors. The target-only visual regression suite exercises the same 112 cases against 111 committed PNGs; the canonical and Studio-state 1440-pixel `/studio/publications` cases intentionally share one identical snapshot. Source screenshots were temporary comparison inputs and were not copied into the target snapshot directory. The production source responds to both a missing dynamic slug such as `/projects/missing-project` and an unmatched path such as `/definitely-not-a-product-route` with HTTP 404, `text/plain`, and the exact nine-byte body `Not Found`. The target intentionally removes the Public shell for those paths and matches that response in curl and Chromium regressions; this is the observed production source contract, not a generic runtime error. ## Governed route migration The migration records 23 TechLog-owned breaking-change evidence IDs with owner `tech-log-frontend`, an atomic same-release route/runtime/manifest migration, and rollback to `05e3d50ba01f01c27f257d2e9040c2bc413ea053`. The accepted registry snapshot digest is `428479ac5845374a82dd7d02a0c59a713106405f031cdc153789174f14c1405b`; its approval reason is `Install approved TechLog Public and Studio route contract`. Final compatibility impact is `none` with no unacknowledged change. ## Restricted-environment test baseline The exact repository aggregate command was run in the managed workspace: ```bash corepack pnpm test:all ``` Its runtime-schema phase passed 3 files/40 tests. The unit phase passed 117 files/1,738 tests and reported 50 failures in three child-process-heavy files: 39 `ci-artifact-contract`, 2 `ci-workflow-generation`, and 9 `http-scenario-evidence`. Every failure was rooted in `spawnSync ... EPERM` in the restricted process sandbox; no `tests/features/tech-log` test failed. The failing files were then reproduced in isolation outside that child-process restriction: ```bash corepack pnpm exec vitest run tests/unit/ci-artifact-contract.test.ts tests/unit/ci-workflow-generation.test.ts tests/unit/http-scenario-evidence.test.ts ``` Result: 3 files/529 tests, 510 passed and the pre-existing 19 environment-only `ci-artifact-contract` cases failed. The 407 `ci-workflow-generation` and 14 `http-scenario-evidence` tests all passed. The remaining exact 19 are the documented provider lifecycle/cgroup, RLIMIT/EMFILE, restrictive-umask, and `/tmp` timing/identity cases; they contain no TechLog code or test. The aggregate phases after unit were also run directly: component 18 files/124 tests, integration 11 files/82 tests under the required child-process scope, reference feature 4 files/13 tests, and recipes 2 files/17 tests all passed. The inventories in this document are human review baselines. Automated coverage is intentionally limited to the two SVG byte contracts, evidence asset lookup behavior, package manager frozen-lockfile verification, committed target visual regressions, and governed registry/release gates. The external source path is never required by committed CI tests.