chore: update versioning and dependencies, remove unused configuration files

This commit is contained in:
Amruth Pillai
2026-09-29 23:34:31 +02:00
parent f82e9f33f3
commit 8ded9de46e
23 changed files with 625 additions and 1109 deletions
-3
View File
@@ -1,3 +0,0 @@
---
exclude_paths:
- "migrations/**"
-5
View File
@@ -1,5 +0,0 @@
self-hosted-runner:
labels:
- blacksmith-2vcpu-ubuntu-2404
- blacksmith-32vcpu-ubuntu-2404
- blacksmith-32vcpu-ubuntu-2404-arm
-31
View File
@@ -1,31 +0,0 @@
config:
default: true
MD007: false
MD009: false
MD010: false
MD012: false
MD013: false
MD001: false
MD022: false
MD024: false
MD025: false
MD028: false
MD031: false
MD032: false
MD033: false
MD034: false
MD036: false
MD040: false
MD041: false
MD046: false
MD060: false
frontMatter: "^---[\\s\\S]*?---"
gitignore: true
globs:
- "**/*.{md,mdx}"
ignores:
- ".design-sync/**"
- "node_modules/**"
- ".turbo/**"
- "dist/**"
@@ -1,39 +0,0 @@
# Imported-table raster CI fix
## Root cause
Hosted runs `34007560930` (PR #3471) and `34007788443` (PR #3472) failed only in
`tests/e2e/specs/imported-table.spec.ts` with `horizontal: 18` instead of Plan 16's
`horizontal: 17`; text and vertical checks passed.
The PDF operator dump from the failed hosted artifact showed 29 table path records matching the Plan 16 contract
(17 horizontal, 12 vertical), followed by an unrelated `constructPath` `endPath` bbox:
`[0, 19.65, 358.93, 20.65]`. Its stroke color was reported as `#cc00cc` only because the helper retained the
last table stroke color. It was a later red section-divider fill/no-paint path, not an extra table border. The old
helper classified every thin bbox after the last matching color state, so it counted this false positive.
The table's explicit width is stable at 300pt, while row height legitimately changes from 30pt to 31pt after the
`Beta!` edit. The helper therefore scopes candidate paths by the fixture's 300pt horizontal grid envelope, not by a
row-height tolerance. Missing or duplicated paths inside that envelope still change the exact 17/12 contract.
## Change
- Added `tests/e2e/fixtures/pdf-borders.ts` with deterministic `countTableBorderGeometry` filtering.
- Updated browser/server PDF inspection in `tests/e2e/specs/imported-table.spec.ts` to use the helper.
- Added `tests/e2e/fixtures/pdf-borders.test.ts`; regression proves old stale-color counting returns 2 horizontal
paths while topology-scoped counting returns 1.
## Verification
- Intent skill inventory: 7 packages, 26 skills; no matching local skill for this E2E/PDF helper.
- Focused helper regression: 1 file, 1 passed.
- Dedicated imported-table E2E: 2 consecutive runs, each 1 passed; both exercise initial, unrelated-edit, and table-edit
stages plus browser and server PDF exports.
- Production build: 3/3 tasks successful.
- Web typecheck via `rtk proxy pnpm --filter web typecheck`: passed (`tsgo --noEmit`).
- Turbo boundaries: 1,443 files across 20 packages, no issues.
- Targeted Biome: 3 files, no issues.
- `git diff --check`: passed.
The root `pnpm typecheck` wrapper was also tried but invokes an incompatible `tsc` path and reports TS5096 for
`allowImportingTsExtensions`; the package's documented `tsgo --noEmit` typecheck passes.
-33
View File
@@ -1,33 +0,0 @@
# Plan 21 implementation evidence
## Revision and scope
- Worktree: `issue-3060-section-heading-visibility`
- Base: current `origin/main` at dispatch, `2a4a1583b` (`fix(pdf): restore Gengar skill rating order (#3473)`)
- Product decisions applied: Q1 explicit Show heading toggle; Q2 Move-to continuations default visible; Q3 visual omission in preview/PDF/DOCX with accessible outline labels retained.
- No `.codegraph/` directory exists in this worktree, so CodeGraph was skipped after the required presence check.
- Intent discovery ran before edits; no matching local skill was available for this schema/PDF/DOCX/web change.
## Implementation
- Added backward-compatible `showHeading` section data for summary, built-ins, and custom sections. `parseResumeData` normalizes absent legacy values to `true`; explicit `false` survives round trips.
- Added heading toggles to built-in/summary and custom section menus. Toggle mutations use `useUpdateResumeData`, preserving undo/autosave/save/reload behavior; legacy absent values are treated as visible. Existing lock fieldset remains authoritative.
- Move-to-created custom sections explicitly set `showHeading: true`, independent of source heading state or copied title.
- `SectionShell` omits complete heading/icon/decoration output when disabled in both icon and no-icon branches. Empty titles still resolve localized defaults.
- DOCX section renderers omit visible heading paragraphs for summary, built-in, and custom sections while retaining content. Screen-reader mirror continues to expose section labels regardless of visual setting.
- Added characterization for Semantic CSS `section[id="..."] section-heading { display: none; }`; body remains while heading is omitted.
- Updated default/sample fixtures, generated schema references, recovery hashes, and compatibility tests; existing Gengar renderer/order changes remain untouched.
## Verification
- `pnpm --filter @reactive-resume/schema test`: 9 files, 132 tests passed.
- `pnpm --filter @reactive-resume/pdf test`: 81 files, 1059 tests passed.
- `pnpm --filter @reactive-resume/docx test`: 9 files, 76 tests passed.
- `pnpm --filter web test`: 135 files, 942 tests passed.
- `pnpm test`: full Turborepo suite passed (19 successful tasks; 10 cache hits).
- Affected typechecks passed: schema, PDF, DOCX, web.
- Focused menu, Move-to, accessible-outline, schema, PDF semantic, and DOCX renderer tests passed.
- `pnpm exec turbo boundaries`: passed (1108 files, 20 packages).
- Read-only `pnpm exec biome check` on 22 changed source/test files: passed; no write-capable `pnpm check` run.
- `git diff --check`: passed.
- Final diff review completed; local commit follows.
@@ -1,32 +0,0 @@
# Plan 23 item-pagination execution evidence
## Scope
Plan 23 steps 1–3 were evaluated from `origin/main` at `368858a56` (Plan 21 / PR #3477 merged). Widow/orphan UI and authored-page continuation guidance remain deferred from this execution, and Semantic CSS was not changed.
## Durable diagnostic matrix
`packages/pdf/src/templates/shared/item-pagination.test.tsx` renders physical PDF pages and checks numbered tokens exactly once for:
- an item that fits remaining space;
- an item that fits a full page but not the remaining space;
- an oversized item taller than one page;
- a two-line paragraph at a boundary;
- nested bullets; and
- built-in plus custom items in an Azurill sidebar/main-column overflow fixture.
The fixture also keeps authored `metadata.layout.pages` separate from renderer-generated physical pages.
The current deterministic baseline is: fit remainder = 1 physical page; full-page-but-not-remainder = 3 pages with sampled tokens on pages 2/2/3; oversized = 5 pages with sampled tokens on pages 1/3/5; two-line boundary = 2 pages; nested bullets = 1 page; Azurill built-in/custom/sidebar = 5 pages with sampled tokens on pages 1/4/5/5/1. Page numbers here are 1-based; every token still appears exactly once.
## Concrete blocker
React PDF's only available item-level keep-together primitive is `View wrap={false}`. A durable renderer fixture with 180 paragraph-like child views shows that a non-wrapping item cannot safely fall back when its content exceeds one page: the renderer omits the oversized tail instead of splitting it. Applying the same prop to shared `SectionItem` would therefore violate the lossless token requirement; no item schema flag or menu control was added.
Do not estimate item height from HTML length, persist physical pages, alter existing Semantic CSS, or claim #3350 complete. A future implementation needs renderer-supported conditional keep-together behavior or an actual measured two-pass fallback that preserves every token.
## Verification
- `pnpm --filter @reactive-resume/pdf exec vitest run src/templates/shared/item-pagination.test.tsx`: 7 tests passed.
- No production source or schema changes made after the unsafe fallback was reproduced.
- Undo/persistence/lock UI coverage is intentionally absent because no item control was shipped; add it only when safe fallback exists.
-157
View File
@@ -1,157 +0,0 @@
# Plan 27 Phase A diagnostic evidence
Date: 2026-09-06
Issue: [#3377](https://github.com/reactive-resume/reactive-resume/issues/3377)<br>
Revision: `2a4a1583b` (`origin/main` at run start)
Scope: Phase A, steps 1–2 only. No resolver, runtime behavior, or remote-source behavior changed.
## Drift and authority
- Worktree started clean and `HEAD` matched `origin/main`; `git diff origin/main...HEAD` was empty.
- Current catalog is `packages/fonts/src/webfontlist.json`. Its web font records point at both Google Fonts static assets and jsDelivr assets; “Google blocked” is not an offline proof.
- Browser preview is `apps/web/src/components/typography/font-display.tsx` and calls `FontFace.load()` against each catalog preview URL.
- Browser PDF preview/download is `apps/web/src/features/resume/export/pdf-document.tsx` → `@reactive-resume/pdf/browser`; registration is `packages/pdf/src/hooks/use-register-fonts.ts`.
- Server PDF is `apps/server/src/http/resume-pdf.ts` → `createResumePdfDownload`; Playwright browser routing cannot observe that process’s outbound font fetches.
- The issue is open and unmodified. PR #3455 is the approved planning PR; its plan/decision log grants execution of this bounded diagnostic and manifest evidence.
## Deterministic fixture
`tests/e2e/fixtures/offline-fonts.ts` seeds one disposable resume after sample creation. It writes the same text into basics and summary, hides the picture, selects IBM Plex Serif 400/700 for body and heading, and marks the row public for the server-PDF surface.
The exact markers are versioned as `offline-font-scripts-v1`:
| Marker | Script or coverage |
| --- | --- |
| `Latin punctuation • — “quotes” €` | Latin plus General Punctuation and currency |
| `简体中文` | Han / Simplified Chinese |
| `العربية` | Arabic |
| `עברית` | Hebrew |
| `ไทย` | Thai |
| `Emoji 🚀` | Emoji |
`tests/e2e/specs/offline-fonts.spec.ts` is opt-in (`OFFLINE_FONT_DIAGNOSTIC=1`) so the normal PR E2E suite does not become network-dependent. Each surface creates a new browser context with persisted auth state, disabled service workers, and no prior browser cache. Every non-same-origin request is aborted and recorded as `{ hostname, path }`; query strings, fragments, headers, bodies, tokens, and full URLs never enter diagnostic output. Reports are attached as JSON and emitted with the same sanitized shape.
The four surfaces are separate tests:
1. Font picker preview opens Typography → Font Family and waits for lazy `FontFace` preview loads.
2. Builder PDF preview navigates to the builder, captures the active PDF canvas, and measures marker-local raster crops.
3. Browser PDF download uses the Export dialog, rasterizes the downloaded PDF, and measures marker-local crops when generation succeeds.
4. Server PDF calls the public PDF endpoint and records text-layer marker presence when generation succeeds.
Builder/browser-PDF reports keep PDF text extraction as a separate `textLayerMarkers` signal; it does not prove visible glyph outlines. Raster evidence attaches a rendered PNG and per-marker crop metrics, failing for blank or tofu-like visible crops. Blocked browser font requests classify browser surfaces as `network-error`. The server report deliberately says `server-outbound-requests-unobservable-from-playwright`; its cold-network gate remains unresolved because server outbound capture and verifiable restart identity require external host-level controls.
## Run protocol and cold-cache boundary
Build and database setup follow `tests/e2e/README.md`. Run each surface in a separately restarted production server process so module-level PDF font registration state cannot leak between controls:
```text
OFFLINE_FONT_DIAGNOSTIC=1 OFFLINE_FONT_DIAGNOSTIC_SERVER_RESTARTED=1 \
pnpm exec playwright test tests/e2e/specs/offline-fonts.spec.ts --grep "picker preview"
```
Stop and restart the production server before repeating the command with `builder PDF`, `browser PDF`, and `server PDF` grep patterns. The environment used for this change had no built `apps/server/dist` or `apps/web/dist`, no running PostgreSQL instance, and no production server to restart, so the cold E2E matrix was not run. This is an explicit infrastructure blocker, not a pass claim. The test records `serverRestartFlag` only as caller input and labels it non-proof; it does not claim a completed cold-network gate.
The current Playwright route guard cannot impose host-level egress denial on Node.js running the server. A genuinely cold server test therefore needs a separately restarted server plus host-level egress capture/deny (for example, a controlled network namespace or an approved outbound proxy). Do not infer server network behavior from an empty browser request list.
## Administrator-hosted manifest proposal
This is a proposal, not an asset download. It intentionally contains only the primary family and glyph fallbacks required by the fixture and current PDF fallback map, not the full catalog.
```json
{
"schemaVersion": "offline-fonts-v1",
"mode": "local-only",
"assetRoot": "/fonts/offline/v1",
"families": {
"IBM Plex Serif": {
"normal": { "400": "ibm-plex-serif/400.ttf", "700": "ibm-plex-serif/700.ttf" },
"italic": { "400": "ibm-plex-serif/400-italic.ttf", "700": "ibm-plex-serif/700-italic.ttf" },
"preview": "ibm-plex-serif/preview.ttf"
},
"IBM Plex Sans": {
"normal": { "400": "ibm-plex-sans/400.ttf", "700": "ibm-plex-sans/700.ttf" },
"italic": { "400": "ibm-plex-sans/400-italic.ttf", "700": "ibm-plex-sans/700-italic.ttf" },
"preview": "ibm-plex-sans/preview.ttf"
},
"Noto Serif": {
"normal": { "400": "noto-serif/400.ttf", "700": "noto-serif/700.ttf" },
"italic": { "400": "noto-serif/400-italic.ttf", "700": "noto-serif/700-italic.ttf" },
"preview": "noto-serif/preview.ttf"
},
"Noto Sans": {
"normal": { "400": "noto-sans/400.ttf", "700": "noto-sans/700.ttf" },
"italic": { "400": "noto-sans/400-italic.ttf", "700": "noto-sans/700-italic.ttf" },
"preview": "noto-sans/preview.ttf"
},
"Noto Sans SC": { "normal": { "400": "noto-sans-sc/400.ttf", "700": "noto-sans-sc/700.ttf" }, "italic": "reuse-normal", "preview": "noto-sans-sc/preview.ttf" },
"Noto Serif SC": { "normal": { "400": "noto-serif-sc/400.ttf", "700": "noto-serif-sc/700.ttf" }, "italic": "reuse-normal", "preview": "noto-serif-sc/preview.ttf" },
"Noto Sans TC": { "normal": { "400": "noto-sans-tc/400.ttf", "700": "noto-sans-tc/700.ttf" }, "italic": "reuse-normal", "preview": "noto-sans-tc/preview.ttf" },
"Noto Serif TC": { "normal": { "400": "noto-serif-tc/400.ttf", "700": "noto-serif-tc/700.ttf" }, "italic": "reuse-normal", "preview": "noto-serif-tc/preview.ttf" },
"Noto Sans JP": { "normal": { "400": "noto-sans-jp/400.ttf", "700": "noto-sans-jp/700.ttf" }, "italic": "reuse-normal", "preview": "noto-sans-jp/preview.ttf" },
"Noto Serif JP": { "normal": { "400": "noto-serif-jp/400.ttf", "700": "noto-serif-jp/700.ttf" }, "italic": "reuse-normal", "preview": "noto-serif-jp/preview.ttf" },
"Noto Sans KR": { "normal": { "400": "noto-sans-kr/400.ttf", "700": "noto-sans-kr/700.ttf" }, "italic": "reuse-normal", "preview": "noto-sans-kr/preview.ttf" },
"Noto Serif KR": { "normal": { "400": "noto-serif-kr/400.ttf", "700": "noto-serif-kr/700.ttf" }, "italic": "reuse-normal", "preview": "noto-serif-kr/preview.ttf" },
"Noto Sans Arabic": { "normal": { "400": "noto-sans-arabic/400.ttf", "700": "noto-sans-arabic/700.ttf" }, "italic": "reuse-normal", "preview": "noto-sans-arabic/preview.ttf" },
"Noto Naskh Arabic": { "normal": { "400": "noto-naskh-arabic/400.ttf", "700": "noto-naskh-arabic/700.ttf" }, "italic": "reuse-normal", "preview": "noto-naskh-arabic/preview.ttf" },
"Noto Sans Hebrew": { "normal": { "400": "noto-sans-hebrew/400.ttf", "700": "noto-sans-hebrew/700.ttf" }, "italic": "reuse-normal", "preview": "noto-sans-hebrew/preview.ttf" },
"Noto Sans Thai": { "normal": { "400": "noto-sans-thai/400.ttf", "700": "noto-sans-thai/700.ttf" }, "italic": "reuse-normal", "preview": "noto-sans-thai/preview.ttf" },
"Noto Emoji": { "normal": { "400": "noto-emoji/400.ttf", "700": "noto-emoji/700.ttf" }, "italic": "reuse-normal", "preview": "noto-emoji/preview.ttf" }
}
}
```
### Candidate source, license, script, and size evidence
Sizes are `Content-Length` bytes from a HEAD request to the exact current catalog assets on 2026-09-06. Responses reported `Content-Encoding: gzip`; these are compressed transfer-size estimates, not a claim about the eventual on-disk representation. Preview paths are aliases to the selected 400 face and add no extra bytes when stored once. Primary sources: [IBM Plex LICENSE.txt](https://github.com/IBM/plex/blob/master/LICENSE.txt), [Noto core LICENSE](https://github.com/notofonts/noto-fonts/blob/main/LICENSE), [Noto CJK Sans LICENSE](https://github.com/notofonts/noto-cjk/blob/main/Sans/LICENSE), and [Noto Emoji font LICENSE](https://github.com/googlefonts/noto-emoji/blob/main/fonts/LICENSE).
| Family | Style/weights in proposal | Current catalog source version | License | Script/fallback role | Gzip bytes (selected files) | Build owner; runtime owners |
| --- | --- | --- | --- | --- | ---: | --- |
| IBM Plex Serif | normal 400/700; italic 400/700 | `fonts.gstatic.com/s/ibmplexserif/v20` | OFL 1.1, Reserved Font Name `Plex` | Primary serif; Latin and punctuation stack | 294,717 | `packages/fonts`; `apps/web` FontDisplay; `packages/pdf` registration |
| IBM Plex Sans | normal 400/700; italic 400/700 | `fonts.gstatic.com/s/ibmplexsans/v23` | OFL 1.1, Reserved Font Name `Plex` | Primary sans | 435,469 | `packages/fonts`; `apps/web` FontDisplay; `packages/pdf` registration |
| Noto Serif | normal 400/700; italic 400/700 | `fonts.gstatic.com/s/notoserif/v33` | OFL 1.1 | Serif punctuation fallback | 1,055,120 | `packages/fonts`; `packages/pdf` fallback registration |
| Noto Sans | normal 400/700; italic 400/700 | `fonts.gstatic.com/s/notosans/v42` | OFL 1.1 | Sans punctuation fallback | 1,236,259 | `packages/fonts`; `packages/pdf` fallback registration |
| Noto Sans SC | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notosanssc/v40` | OFL 1.1 (Noto CJK) | Simplified Han; CJK fallback | 12,766,416 | `packages/fonts`; `packages/pdf` CJK fallback |
| Noto Serif SC | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notoserifsc/v35` | OFL 1.1 (Noto CJK) | Simplified Han serif fallback | 17,350,185 | `packages/fonts`; `packages/pdf` CJK fallback |
| Noto Sans TC | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notosanstc/v39` | OFL 1.1 (Noto CJK) | Traditional Han fallback | 8,628,278 | `packages/fonts`; `packages/pdf` CJK fallback |
| Noto Serif TC | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notoseriftc/v36` | OFL 1.1 (Noto CJK) | Traditional Han serif fallback | 11,804,923 | `packages/fonts`; `packages/pdf` CJK fallback |
| Noto Sans JP | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notosansjp/v56` | OFL 1.1 (Noto CJK) | Kana and Japanese Han fallback | 6,383,035 | `packages/fonts`; `packages/pdf` CJK fallback |
| Noto Serif JP | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notoserifjp/v33` | OFL 1.1 (Noto CJK) | Kana and Japanese Han serif fallback | 8,685,862 | `packages/fonts`; `packages/pdf` CJK fallback |
| Noto Sans KR | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notosanskr/v39` | OFL 1.1 (Noto CJK) | Hangul and Korean Han fallback | 6,102,888 | `packages/fonts`; `packages/pdf` CJK fallback |
| Noto Serif KR | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notoserifkr/v31` | OFL 1.1 (Noto CJK) | Hangul and Korean Han serif fallback | 11,113,442 | `packages/fonts`; `packages/pdf` CJK fallback |
| Noto Sans Arabic | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notosansarabic/v33` | OFL 1.1 | Arabic sans fallback | 178,455 | `packages/fonts`; `packages/pdf` script fallback |
| Noto Naskh Arabic | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notonaskharabic/v44` | OFL 1.1 | Arabic serif fallback | 190,924 | `packages/fonts`; `packages/pdf` script fallback |
| Noto Sans Hebrew | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notosanshebrew/v50` | OFL 1.1 | Hebrew fallback for both serif/sans slots | 55,707 | `packages/fonts`; `packages/pdf` script fallback |
| Noto Sans Thai | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notosansthai/v29` | OFL 1.1 | Thai fallback for both serif/sans slots | 55,173 | `packages/fonts`; `packages/pdf` script fallback |
| Noto Emoji | normal 400/700; italic reuses normal | `fonts.gstatic.com/s/notoemoji/v62` | OFL 1.1 for font files; assets/tools have separate licenses | Emoji outline fallback; verify renderer support | 1,153,847 | `packages/fonts`; `packages/pdf` script fallback |
Estimated transfer size for all rows and listed styles: **87,490,700 bytes (~83.44 MiB)**. This confirms why a full-catalog bundle is out of scope. A later implementation should subset by declared glyph requirements or make the administrator choose fallback families; it must not silently fetch another CDN.
### Source and license obligations
- Pin an upstream release/commit and retain source attribution plus the complete applicable license with hosted assets. Do not use mutable `@latest` URLs as runtime sources.
- IBM Plex’s license has Reserved Font Name `Plex`; modified/subset outputs must follow OFL naming requirements.
- Noto core, Noto CJK, and Noto Emoji font files are OFL 1.1, but Noto Emoji documents separate Apache/public-domain treatment for tools and flag image assets. Bundle only font files unless those other assets are intentionally needed and separately attributed.
- License checks are build-owner responsibility (`packages/fonts`/tooling); runtime owners (`apps/web` and `packages/pdf`) consume only the validated manifest.
### Missing-family and missing-asset behavior
Local mode must resolve only same-origin administrator-hosted manifest paths. If imported resume data names an unavailable family, show an actionable missing-family error naming the family and required local asset; apply a configured local fallback only when the administrator explicitly supplied one. If a required weight/style/fallback asset is absent, fail the affected preview/export with an actionable diagnostic containing family/style/weight and local path. Never retry Google Fonts, jsDelivr, or any other remote URL in local mode.
Standard PDF families (Helvetica, Courier, Times-Roman) remain file-free. They do not prove that a document containing punctuation, CJK, Arabic, Hebrew, Thai, or emoji is network-free; the script fallback rows remain required.
## Verification record
Completed read-only checks before handoff:
- CodeGraph exploration of font catalog, picker preview, browser PDF, server PDF, and existing fallback tests.
- `pnpm dlx @tanstack/intent@latest list`: no matching local intent skill for this work.
- `pnpm exec biome check tests/e2e/specs/offline-fonts.spec.ts tests/e2e/fixtures/offline-fonts.ts turbo.json`: passed.
- `git diff --check`: passed.
- `pnpm --filter @reactive-resume/fonts test`: passed (55 tests).
- `pnpm --filter @reactive-resume/pdf exec vitest run src/hooks/use-register-fonts.test.ts`: passed (35 tests).
- Web typography/regression suite: passed (940 tests across 135 files); web and server package typechecks passed.
- `pnpm exec playwright test tests/e2e/specs/offline-fonts.spec.ts --list`: passed (4 diagnostic tests collected).
- E2E diagnostic execution: blocked by missing build outputs and unavailable PostgreSQL/server; no success claim made.
- `pnpm exec turbo boundaries`: passed on fresh rerun (Turbo 2.10.12, 1108 files, no issues).
The implementation intentionally stops at diagnostic fixtures and manifest evidence. Shared source resolution, asset hosting, local-mode configuration, and production behavior remain Phase A step 3+ work.
@@ -1,22 +0,0 @@
# Plan 27A remediation round 2
Date: 2026-09-06
Base: `ae8e2f76f`
## Focused fixes
- Removed multilingual markers from the fixture headline. Each marker now exists only in its dedicated summary paragraph.
- Added pure marker-location helpers. Marker lookup joins PDF text items, supports markers split across items, rejects duplicate occurrences, and rejects non-whitespace neighbors that could contaminate a local crop.
- Raster measurement still scans with antialiasing padding but counts ink only inside the marker box, preventing neighboring glyphs from making blank or tofu-like evidence pass.
- Browser PDF download now separates download errors from post-download evidence errors. A received download with failed rasterization is reported as `unresolved-raster-evidence-error` and fails the opt-in test rather than passing as a generic download error.
- Added focused pure tests covering duplicate, split, neighboring, blank, and tofu-like cases.
- Removed trailing spaces from `plan-27a-remediation.md`.
## Verification
- `pnpm exec vitest run tests/e2e/fixtures/offline-font-markers.test.ts` — 5/5 passed.
- `pnpm exec biome check tests/e2e/specs/offline-fonts.spec.ts tests/e2e/fixtures/offline-fonts.ts tests/e2e/fixtures/offline-font-markers.ts tests/e2e/fixtures/offline-font-markers.test.ts` — passed.
- `pnpm exec playwright test tests/e2e/specs/offline-fonts.spec.ts --list` — 4 tests collected.
- `git diff --check` — passed after remediation-document whitespace cleanup.
Full diagnostic E2E remains opt-in and was not run in this focused round. Server outbound request capture and verifiable restart identity remain explicit external host-level blockers; no production resolver changes were made.
-24
View File
@@ -1,24 +0,0 @@
# Plan 27A remediation
Date: 2026-09-06
Base: `61b58ae9a`
Scope: concrete findings from `.orchestration/plan-27a-independent-review.md` only.
## Remediated findings
- Builder PDF preview and browser PDF download now produce raster evidence. The fixture stores each multilingual marker in its own summary paragraph, allowing the diagnostic to locate marker-local PDF text boxes and measure only those raster crops. Reports attach a rendered PNG plus per-marker `inkPixels`, trimmed dimensions, and status. Blank and tofu-like crops fail assertions; no whole-page snapshot is used.
- PDF text extraction is reported separately as `textLayerMarkers`. It is not described or asserted as proof of visible glyph outlines.
- Server PDF output remains text-extraction-only and is explicitly classified as `serverGateStatus: unresolved-external-host-level-blocker`. `serverRestartFlag` is caller input, not restart proof. Browser Playwright routing is not used to infer server egress, and no production resolver or instrumentation behavior was added.
- `.orchestration/plan-27a-diagnostic.md` now records a fresh boundaries pass and the corrected `87,490,700 bytes (~83.44 MiB)` arithmetic.
- Diagnostic remains opt-in through `OFFLINE_FONT_DIAGNOSTIC=1`; normal CI behavior remains unchanged. Request logs stay sanitized to hostname and pathname.
## Verification
- `pnpm exec biome check tests/e2e/specs/offline-fonts.spec.ts tests/e2e/fixtures/offline-fonts.ts` — passed.
- `git diff --check` — passed.
- `pnpm exec playwright test tests/e2e/specs/offline-fonts.spec.ts --list` — 4 tests collected.
- `pnpm --filter @reactive-resume/fonts test` — 55/55 passed.
- `pnpm --filter @reactive-resume/pdf exec vitest run src/hooks/use-register-fonts.test.ts` — 35/35 passed.
- `pnpm exec turbo boundaries` — passed on fresh rerun (Turbo 2.10.12, 1108 files, no issues).
Full diagnostic E2E remains unrun because this environment lacks production build output, PostgreSQL, and a production server. Server cold-network capture and verifiable restart identity remain external host-level blockers by design; this remediation does not claim that gate is complete.
@@ -1,17 +0,0 @@
# Issue 3350 remediation evidence
## Findings addressed
- `item-pagination.test.tsx` now derives complete numbered-token inventories for each generated fixture and asserts every token exactly once. Sampled token-to-physical-page placement checks remain separate.
- Pagination fixtures snapshot `metadata.layout.pages` before rendering and assert authored layout pages are unchanged afterward. Overflow fixtures also assert physical PDF page count exceeds authored page count.
- Unsafe `wrap={false}` renderer coverage remains diagnostic-only; no item controls, schema flags, or runtime behavior were added.
## Verification
- `rtk proxy pnpm --filter @reactive-resume/pdf exec vitest run src/semantic/pagination.test.tsx src/templates/shared/item-pagination.test.tsx` — 2 files, 11 tests passed.
- `rtk proxy pnpm --filter @reactive-resume/pdf typecheck` — passed.
- `rtk proxy pnpm exec biome check packages/pdf/src/templates/shared/item-pagination.test.tsx` — passed.
- `rtk proxy pnpm exec turbo boundaries` — passed; 1109 files checked.
- `rtk git diff --check origin/main...HEAD` — passed.
Only PDF test coverage and this evidence file changed; production behavior remains untouched.
+1 -2
View File
@@ -168,7 +168,6 @@ pnpm --filter @reactive-resume/pdf test src/templates/shared/filtering.test.ts
pnpm --filter @reactive-resume/pdf exec vitest run src/templates/shared/filtering.test.ts -t "filterItems"
pnpm --filter @reactive-resume/pdf test:coverage
pnpm exec biome check apps/web/src/features/resume
pnpm exec markdownlint-cli2 --no-globs AGENTS.md
pnpm exec turbo boundaries
```
@@ -199,7 +198,7 @@ pnpm test:e2e:ui
- TypeScript is strict, including `exactOptionalPropertyTypes`, `noUncheckedIndexedAccess`, and unused-symbol checks; packages typecheck with `tsgo --noEmit`.
- Biome uses tabs, double quotes, 120-column lines, separated type imports, organized import groups, and sorted Tailwind classes in `clsx`, `cva`, and `cn`. Use existing file naming and feature-local conventions.
- **`pnpm check` modifies files**: it regenerates PDF translations, runs Biome with `--write --unsafe`, runs Markdown fixes, and checks GitHub Actions syntax. Call out its write behavior and review the diff; use narrow non-mutating commands when inspecting unrelated edits.
- **`pnpm check` modifies files**: it regenerates PDF translations and runs Biome with `--write --unsafe`. Call out its write behavior and review the diff; use narrow non-mutating commands when inspecting unrelated edits.
- Lefthook's pre-commit hook checks conflict markers and runs write-capable Biome on supported staged files, staging fixes. The commit-message hook enforces Conventional Commits (`fix:`, `feat:`, `docs:`, etc.).
## Build and deployment
+1 -1
View File
@@ -1,5 +1,5 @@
---
version: 2.0-alpha
version: 6.0.0
name: Reactive Resume · Desk & Paper
description: A quiet, warm desk around a bright page. The resume is the only white, detailed object on screen; one moss-green accent marks the next action. Light and dark themes, with the page always white.
colors:
+20 -20
View File
@@ -15,30 +15,30 @@
"test:agent": "vitest run --reporter=agent --reporter=json --outputFile.json=reports/vitest-results.json --passWithNoTests"
},
"dependencies": {
"@ai-sdk/anthropic": "^4.0.65",
"@ai-sdk/cerebras": "^3.0.57",
"@ai-sdk/cohere": "^4.0.50",
"@ai-sdk/deepseek": "^3.0.54",
"@ai-sdk/fireworks": "^3.0.60",
"@ai-sdk/google": "^4.0.82",
"@ai-sdk/groq": "^4.0.50",
"@ai-sdk/mistral": "^4.0.52",
"@ai-sdk/openai": "^4.0.78",
"@ai-sdk/openai-compatible": "^3.0.57",
"@ai-sdk/perplexity": "^5.0.1",
"@ai-sdk/togetherai": "^3.0.58",
"@ai-sdk/xai": "^5.0.10",
"@aws-sdk/client-s3": "^3.1141.0",
"@ai-sdk/anthropic": "^4.0.68",
"@ai-sdk/cerebras": "^3.0.59",
"@ai-sdk/cohere": "^4.0.52",
"@ai-sdk/deepseek": "^3.0.56",
"@ai-sdk/fireworks": "^3.0.62",
"@ai-sdk/google": "^4.0.85",
"@ai-sdk/groq": "^4.0.52",
"@ai-sdk/mistral": "^4.0.54",
"@ai-sdk/openai": "^4.0.81",
"@ai-sdk/openai-compatible": "^3.0.59",
"@ai-sdk/perplexity": "^5.0.3",
"@ai-sdk/togetherai": "^3.0.60",
"@ai-sdk/xai": "^5.0.12",
"@aws-sdk/client-s3": "^3.1143.0",
"@better-auth/api-key": "^1.7.6",
"@better-auth/drizzle-adapter": "^1.7.6",
"@better-auth/infra": "^0.4.11",
"@better-auth/infra": "^0.4.13",
"@better-auth/oauth-provider": "^1.7.6",
"@better-auth/passkey": "^1.7.6",
"@bramus/specificity": "^2.4.2",
"@formepdf/core": "0.25.0",
"@formepdf/react": "0.25.0",
"@hono/node-server": "^2.1.1",
"@modelcontextprotocol/sdk": "^1.30.1",
"@hono/node-server": "^2.1.3",
"@modelcontextprotocol/sdk": "^1.31.0",
"@orpc/client": "^1.15.4",
"@orpc/experimental-ratelimit": "^1.15.4",
"@orpc/json-schema": "^1.15.4",
@@ -57,7 +57,7 @@
"@uiw/color-convert": "^2.10.3",
"@vercel/blob": "^2.8.0",
"@vercel/functions": "^3.9.9",
"ai": "^7.0.118",
"ai": "^7.0.122",
"bcrypt": "^6.0.0",
"better-auth": "1.7.6",
"cjk-regex": "^3.5.0",
@@ -68,12 +68,12 @@
"fast-json-patch": "^3.1.1",
"fast-png": "^8.0.0",
"fflate": "^0.8.3",
"hono": "^4.13.9",
"hono": "^4.13.11",
"ioredis": "^6.0.0",
"jose": "^6.2.12",
"jsonrepair": "^3.15.0",
"node-html-parser": "^9.0.4",
"nodemailer": "^10.0.11",
"nodemailer": "^10.0.12",
"ollama-ai-provider-v2": "^4.0.1",
"pg": "^8.23.0",
"react": "^19.3.0",
+5 -5
View File
@@ -16,10 +16,10 @@
"lingui:extract": "lingui extract --clean --overwrite"
},
"dependencies": {
"@ai-sdk/react": "^4.0.121",
"@ai-sdk/react": "^4.0.125",
"@base-ui/react": "^1.8.0",
"@better-auth/api-key": "^1.7.6",
"@better-auth/infra": "^0.4.11",
"@better-auth/infra": "^0.4.13",
"@better-auth/oauth-provider": "^1.7.6",
"@better-auth/passkey": "^1.7.6",
"@codemirror/autocomplete": "^6.20.3",
@@ -34,7 +34,7 @@
"@dnd-kit/utilities": "^3.2.2",
"@fontsource-variable/anybody": "^5.3.0",
"@fontsource-variable/martian-mono": "^5.3.0",
"@lezer/highlight": "^1.2.4",
"@lezer/highlight": "^1.2.5",
"@lingui/core": "^6.8.0",
"@lingui/react": "^6.8.0",
"@orpc/client": "^1.15.4",
@@ -70,7 +70,7 @@
"@types/js-cookie": "^3.0.6",
"@uiw/color-convert": "^2.10.3",
"@uiw/react-color-colorful": "^2.10.3",
"ai": "^7.0.118",
"ai": "^7.0.122",
"better-auth": "1.7.6",
"cmdk": "^1.1.1",
"es-toolkit": "^1.52.0",
@@ -78,7 +78,7 @@
"fuse.js": "^7.5.0",
"immer": "^11.1.18",
"js-cookie": "^3.0.8",
"motion": "^13.4.4",
"motion": "^13.4.6",
"pdfjs-dist": "6.3.289",
"prettier": "^3.9.9",
"qrcode.react": "^4.2.0",
+5 -7
View File
@@ -1,7 +1,7 @@
{
"name": "reactive-resume",
"description": "Reactive Resume is a free and open-source resume builder that makes it easy to create, update, and share your resume.",
"version": "5.3.2",
"version": "6.0.0",
"private": true,
"license": "MIT",
"author": {
@@ -16,7 +16,7 @@
"engines": {
"node": "24.x"
},
"packageManager": "pnpm@12.6.0",
"packageManager": "pnpm@12.8.1",
"workspaces": [
"apps/*",
"packages/*",
@@ -24,7 +24,7 @@
],
"scripts": {
"build": "pnpm pdf:translations && turbo run build",
"check": "pnpm pdf:translations && biome check --write --unsafe . && markdownlint-cli2 --fix && github-actionlint -shellcheck= -pyflakes=",
"check": "pnpm pdf:translations && biome check --write --unsafe .",
"docs:gen": "pnpm --filter server docs:gen && pnpm --filter @reactive-resume/tooling docs:gen",
"db:generate": "dotenvx run --ignore=MISSING_ENV_FILE -f .env.local -- turbo run db:generate --filter=@reactive-resume/db",
"db:migrate": "dotenvx run --ignore=MISSING_ENV_FILE -f .env.local -- turbo run db:migrate --filter=@reactive-resume/db",
@@ -48,7 +48,7 @@
"@biomejs/biome": "^2.5.14",
"@commitlint/cli": "^21.2.3",
"@commitlint/config-conventional": "^21.2.3",
"@dotenvx/dotenvx": "^1.75.1",
"@dotenvx/dotenvx": "^2.31.1",
"@playwright/test": "^1.63.0",
"@reactive-resume/config": "workspace:*",
"@testing-library/jest-dom": "^7.0.1",
@@ -57,11 +57,9 @@
"@types/node": "^26.6.3",
"@types/pg": "^8.23.1",
"@vitest/coverage-v8": "^5.0.2",
"github-actionlint": "1.7.12",
"happy-dom": "^20.14.5",
"knip": "^6.38.0",
"lefthook": "^2.1.14",
"markdownlint-cli2": "0.23.3",
"lefthook": "^2.1.15",
"pg": "^8.23.0",
"turbo": "^2.11.5",
"typescript": "^7.0.2",
+1 -1
View File
@@ -27,7 +27,7 @@
},
"devDependencies": {
"@reactive-resume/config": "workspace:*",
"ai": "^7.0.118",
"ai": "^7.0.122",
"@typescript/native-preview": "7.0.0-dev.20260707.2",
"typescript": "^7.0.2"
}
+16 -16
View File
@@ -24,20 +24,20 @@
"test:agent": "vitest run --reporter=agent --reporter=json --outputFile.json=reports/vitest-results.json --passWithNoTests"
},
"dependencies": {
"@ai-sdk/anthropic": "^4.0.65",
"@ai-sdk/cerebras": "^3.0.57",
"@ai-sdk/cohere": "^4.0.50",
"@ai-sdk/deepseek": "^3.0.54",
"@ai-sdk/fireworks": "^3.0.60",
"@ai-sdk/google": "^4.0.82",
"@ai-sdk/groq": "^4.0.50",
"@ai-sdk/mistral": "^4.0.52",
"@ai-sdk/openai": "^4.0.78",
"@ai-sdk/openai-compatible": "^3.0.57",
"@ai-sdk/perplexity": "^5.0.1",
"@ai-sdk/togetherai": "^3.0.58",
"@ai-sdk/xai": "^5.0.10",
"@aws-sdk/client-s3": "^3.1141.0",
"@ai-sdk/anthropic": "^4.0.68",
"@ai-sdk/cerebras": "^3.0.59",
"@ai-sdk/cohere": "^4.0.52",
"@ai-sdk/deepseek": "^3.0.56",
"@ai-sdk/fireworks": "^3.0.62",
"@ai-sdk/google": "^4.0.85",
"@ai-sdk/groq": "^4.0.52",
"@ai-sdk/mistral": "^4.0.54",
"@ai-sdk/openai": "^4.0.81",
"@ai-sdk/openai-compatible": "^3.0.59",
"@ai-sdk/perplexity": "^5.0.3",
"@ai-sdk/togetherai": "^3.0.60",
"@ai-sdk/xai": "^5.0.12",
"@aws-sdk/client-s3": "^3.1143.0",
"@orpc/client": "^1.15.4",
"@orpc/experimental-ratelimit": "^1.15.4",
"@orpc/server": "^1.15.4",
@@ -50,7 +50,7 @@
"@reactive-resume/schema": "workspace:*",
"@reactive-resume/utils": "workspace:*",
"@vercel/blob": "^2.8.0",
"ai": "^7.0.118",
"ai": "^7.0.122",
"bcrypt": "^6.0.0",
"better-auth": "1.7.6",
"drizzle-orm": "1.0.0-rc.4",
@@ -70,7 +70,7 @@
"@reactive-resume/config": "workspace:*",
"@types/bcrypt": "^6.0.0",
"@types/pg": "^8.23.1",
"@types/sanitize-html": "^2.16.1",
"@types/sanitize-html": "^2.16.2",
"@typescript/native-preview": "7.0.0-dev.20260707.2",
"es-toolkit": "^1.52.0",
"pg": "^8.23.0",
+1 -1
View File
@@ -17,7 +17,7 @@
"dependencies": {
"@better-auth/api-key": "^1.7.6",
"@better-auth/drizzle-adapter": "^1.7.6",
"@better-auth/infra": "^0.4.11",
"@better-auth/infra": "^0.4.13",
"@better-auth/oauth-provider": "^1.7.6",
"@better-auth/passkey": "^1.7.6",
"@reactive-resume/db": "workspace:*",
+1 -1
View File
@@ -16,7 +16,7 @@
"dependencies": {
"@reactive-resume/schema": "workspace:*",
"@reactive-resume/utils": "workspace:*",
"docx": "^9.8.0"
"docx": "^9.8.1"
},
"devDependencies": {
"@reactive-resume/config": "workspace:*",
+1 -1
View File
@@ -17,7 +17,7 @@
},
"dependencies": {
"@reactive-resume/env": "workspace:*",
"nodemailer": "^10.0.11",
"nodemailer": "^10.0.12",
"react": "^19.3.0",
"react-email": "^6.11.0"
},
+1 -1
View File
@@ -16,7 +16,7 @@
"test:agent": "vitest run --reporter=agent --reporter=json --outputFile.json=reports/vitest-results.json --passWithNoTests"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.30.1",
"@modelcontextprotocol/sdk": "^1.31.0",
"@orpc/server": "^1.15.4",
"@reactive-resume/ai": "workspace:*",
"@reactive-resume/api": "workspace:*",
+1 -1
View File
@@ -42,7 +42,7 @@
"@napi-rs/canvas": "1.0.9",
"@reactive-resume/config": "workspace:*",
"@types/react": "^19.3.0",
"@types/react-reconciler": "^0.33.0",
"@types/react-reconciler": "^0.33.1",
"@typescript/native-preview": "7.0.0-dev.20260707.2",
"pdfjs-dist": "6.3.289",
"typescript": "^7.0.2"
+571 -689
View File
File diff suppressed because it is too large Load Diff