224 lines
11 KiB
Markdown
224 lines
11 KiB
Markdown
# 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 on `4375` and the target `dist/server.mjs` production artifact on `4174`
|
||
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 normalized recursive
|
||
product-subtree tags, ordered children, complete classes, relevant
|
||
attributes, text/ARIA relationships, response metadata, boot lifecycle, and
|
||
console/request failure comparison.
|
||
|
||
The only attributes omitted by name after concrete diagnostics are React
|
||
Router `data-discover`, Next Image `data-nimg`/`decoding`/`srcset`, and Next SSR
|
||
`selected`; generated React IDs and CSS-module hashes are normalized by value.
|
||
No broad attribute class is omitted.
|
||
|
||
| Evidence group | Cases |
|
||
| --- | ---: |
|
||
| 27 canonical routes at 360 and 1440 pixels | 54 |
|
||
| Every additional known Public fixture slug/version | 18 |
|
||
| 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** | **130** |
|
||
|
||
Result: 130/130 passed, zero failed, zero different pixels, all recursive
|
||
DOM/class/attribute/text/ARIA trees and HTTP response metadata equal, and zero
|
||
unexplained source or target console/request errors. The target-only visual
|
||
regression suite exercises the same 130 cases against 129 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 checked clean-checkout command is
|
||
`TZ=Asia/Seoul corepack pnpm verify:tech-log-source-parity`; it runs directly
|
||
under the installed Node 24 runtime and has no `tsx` dependency. Durable
|
||
evidence is committed at
|
||
`docs/operations/evidence/tech-log-source-parity.json`. It records 178 source
|
||
checksums with tree digest
|
||
`6724c2f898eefc62d2fc0ee695bccc3ae61a69c5153ed43c69f2cf99ee45bca5`,
|
||
target candidate `3a7c5deca06679fb9b8710da2cce87bbca07ce8a`, build-manifest digest
|
||
`3579650faa482f566553c00d8b4a05a05b4f7a1ab93b83e48676289bbcf02984`,
|
||
Vite-manifest digest
|
||
`cfd583ed7b6c27dce7f47389447608636b6b9df3e28df00c6416674da2c7c46d`,
|
||
case inventory digest
|
||
`5689bcdb5d5637205cdeb92b7c57f72d99f0b039818b8f90afdde526bbafe0ac`,
|
||
and evidence payload digest
|
||
`f046047beded19ce468be607dcf99c6b74d4e07323457ec7145c56d2f67d2c79`.
|
||
|
||
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;charset=UTF-8`, and the exact nine-byte body `Not Found`. The
|
||
target production server intentionally removes the Public shell for those
|
||
paths and matches that response in direct HTTP and Chromium regressions. Known
|
||
Public routes and all known Studio routes remain SPA-served; `/studio/*`
|
||
unknown paths preserve the source's in-shell HTML with HTTP 404. This is the
|
||
observed production source contract, not a generic runtime error.
|
||
|
||
## Accessibility review boundary
|
||
|
||
Automated Chromium `@a11y` coverage passes 29/29. The source-controlled manual
|
||
inventory contains exactly the 27 installed route IDs and removes the obsolete
|
||
starter records. Every human record remains `pending-manual-review` until one
|
||
reviewer evaluates keyboard, focus, modal/error behavior, color, reduced
|
||
motion, and screen-reader output against immutable candidate
|
||
`3a7c5deca06679fb9b8710da2cce87bbca07ce8a`. Therefore
|
||
`corepack pnpm review:a11y-manual` intentionally exits nonzero with 27
|
||
incomplete records and `release IDs do not match`; neither the manual gate nor
|
||
`FE-GATE-009` is represented as passing. The exact completion format is in
|
||
`docs/accessibility/manual-checklist.md`, and signed evidence must be committed
|
||
separately after it cites the candidate SHA.
|
||
|
||
## 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 fresh staged-candidate runtime-schema phase passed 3 files/40 tests. The
|
||
unit phase passed 122 files/1,773 tests and reported 19 failures, all in the
|
||
pre-existing `ci-artifact-contract` provider/cgroup, RLIMIT/EMFILE,
|
||
restrictive-umask, `/tmp`, timing, and identity environment cases. No
|
||
`tests/features/tech-log` test failed. A pre-staging diagnostic run also found
|
||
39 `APP_HOME` release-inventory failures because new serving files were not yet
|
||
visible to `git ls-files`; staging the complete candidate fixed that test
|
||
precondition, and all 39 disappeared. The same run's one guardian aggregate
|
||
timeout passed 1/1 in isolation and 21/21 in the fresh staged aggregate.
|
||
|
||
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 same 19 environment-only
|
||
`ci-artifact-contract` cases failed. The 407 `ci-workflow-generation` and 14
|
||
`http-scenario-evidence` tests all passed. These 19 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.
|