Commit Graph
6114 Commits
Author SHA1 Message Date
Amruth Pillai 9dd38433d6 test(e2e): drive the Design panel
template-switch now previews a template on hover, applies it from its card,
checks it after a reload and undoes a switch from the toast. The section
helper opens Design groups and the exact-value sections inside Advanced.
2026-09-28 19:04:27 +02:00
Amruth Pillai 1ef7c9fa10 feat(web): rebuild Design with template previews, presets and Fit
The Design mode is a single panel with a sticky group nav: Template, Type,
Color, Page and a collapsed Advanced.

- Template: filter chips, and thumbnails rendered from the user's own
  content at idle time, cached by template and content. Hovering or
  focusing a card (holding it, on touch) previews the template on the page
  with a "Previewing" chip; leaving the cards or Esc restores it; a click
  applies it with an Undo toast. Two-column templates get a sidebar
  sub-panel for its width and sections.
- Type: five font pairings, text size 9-12.5 pt and density. Color: eight
  accents and a hex field with its contrast on white, offering a darker
  shade below 4.5:1. Page: paper, language, margins, icons and link
  underlines.
- Advanced: the date format, every exact-value editor, custom CSS and
  Reset to template defaults.
- When content runs past the authored pages the canvas says by how many
  lines and offers Fit, which tightens density, then margins, then size
  (never below 9 pt), re-rendering after each step, as one undo step.
- Phones get the groups in a half-height sheet over the live page.

The template gallery dialog, the Template section, the collapsible section
chrome and its collapse store are gone. ATS design findings now open the
Design group that fixes them. The desktop panel is a containing block, so
screen-reader text deep in a long panel no longer stretches the document.
2026-09-28 19:04:21 +02:00
Amruth Pillai 85352ee11b feat(schema): describe template layouts in one place
Columns, sidebar side, header placement and ATS safety for every template
now live in templateLayouts. The template gallery metadata and the layout
editor read it, and a DOCX test checks the two-column configurations
against it.
2026-09-28 19:04:03 +02:00
Amruth Pillai 7244485d6e docs: note when the preview moves to a worker 2026-09-28 18:20:48 +02:00
Amruth Pillai 1b079dd5bd docs: log M3 in the redesign plan 2026-09-28 18:20:29 +02:00
Amruth Pillai de85121f5e chore(i18n): extract catalogs for the Write panel 2026-09-28 18:20:28 +02:00
Amruth Pillai e2e5c15580 test(e2e): cover inline editing and click-to-select
Specs follow the outline rows, the eye on each row, the photo row, the
structured dates and the Full name field, and a new spec checks that a
click on the page opens its entry and focusing a field outlines its block.
The download-preference spec waits for the share address after a reload.
2026-09-28 18:20:27 +02:00
Amruth Pillai a82741f42a feat(web): edit resumes inline in the Write panel
Write becomes the Basics card, the outline of sections in print order and
Add section. Entries open in place (one at a time, the editor selection),
save as you type and show drafts as "Draft · not printed". Dates use a
structured field with a Present switch and the review note for text that
wasn't read exactly; descriptions use a restricted rich-text toolbar shown
on focus. Sections and entries reorder by drag or Alt+Up/Down, rows carry
the eye, count and every section option, and deleting shows Undo.

Clicking the page opens the entry and scrolls it into view; focusing a field
outlines its block. Phones push an open entry full screen. While a field
has focus the preview waits for a pause in typing.

The left section sidebar, the entry dialogs and the hidden-sections list are
removed.
2026-09-28 18:20:26 +02:00
Amruth Pillai bda01febd5 feat(schema): structured resume dates with a read-time upgrade and dual write
Dated entries and roles carry dates (start, end, present, and raw when the
text couldn't be read exactly). The parser moves to the schema package and
reports how each date was written; parseResumeData fills dates, infers the
date format from how dates were typed and rewrites the legacy period/date
text from them, so older clients and API readers keep working. API writes
sync against the stored data, so an edit to the text alone is read back
into dates.

getById and getBySlug return upgraded data, ATS date rules and sorting read
dates, JSON Resume and LinkedIn imports map their dates directly, entry
titles may be empty (drafts aren't printed), and the MCP schema resource is
generated live in place of the stale schema.json.
2026-09-28 18:20:18 +02:00
Amruth Pillai fa19b891db docs: log M2 in the redesign plan 2026-09-28 17:18:12 +02:00
Amruth Pillai 91f1aba2e5 chore(i18n): extract catalogs for the editor shell 2026-09-28 17:18:11 +02:00
Amruth Pillai ffa16f2efa test(e2e): drive the new editor bar, modes and share sheet
openSidebarSection now switches to the mode that hosts a section or opens the
Share & export sheet, and openDownloadDialog opens every format from the
Download PDF split button. Specs follow the back link, the save status line,
the document menu, the zoom bar and page-scale zoom.
2026-09-28 17:18:10 +02:00
Amruth Pillai f2a76b2f69 feat(web): replace the builder with the Desk & Paper editor shell
One editor at /builder/$resumeId: a bar with the document menu and save
status, the Write, Design and Check modes (in ?mode=), undo, history,
assistant, Share and the Download PDF split button, over the panel and the
page canvas. Tablets get a drawer that can be pinned in landscape; phones
get Write, Page, Design and Check tabs.

The canvas renders pages at the zoom level (60-150%, Fit), outlines the
selected entry, links page clicks to the panel and panel focus to the page,
and offers Edit entry on phones. Share & export hosts sharing, statistics and
every download format. Offline, the panel explains the state and Share and
Download wait for a connection.

Until their milestones land, the modes host today's section editors, design
sections and ATS check. The resizable-panel shells, rails, dock, header,
mobile shell and react-zoom-pan-pinch are removed.
2026-09-28 17:18:04 +02:00
Amruth Pillai 639abf12b6 feat(web): keep unsaved drafts on the device and deepen undo
Failed saves report Offline or Not saved with a retry, keep the draft in
localStorage per resume, replay it when the connection returns and restore
it when the editor opens again. Undo keeps 200 steps as shared immer trees,
merges typing in one field within a second and keeps structural actions as
steps of their own.
2026-09-28 17:17:56 +02:00
Amruth Pillai f73238ba3b feat(pdf): pass the page map through the browser renderer 2026-09-28 17:17:56 +02:00
Amruth Pillai a887a72d77 feat(ui): add a breakpoint hook, panel icons and CSS-drawn icon glyphs
Icons now draw their ligature from data-icon in a pseudo-element, so icon
names stay out of copied text, find-in-page and text queries. useBreakpoint
reports the design system's mobile, tablet, desktop and wide ranges.
2026-09-28 17:17:54 +02:00
Amruth Pillai 90d7d0a19b docs: document the Desk & Paper design system
Rewrite DESIGN.md for the new tokens, type, icons, motion and
components, add the redesign's terms to GLOSSARY.md, and log M1 in the
redesign plan.
2026-09-28 16:29:36 +02:00
Amruth Pillai 9e041e140b chore(i18n): extract catalogs for the System theme option
Also picks up LinkedIn import strings that hadn't been extracted yet.
2026-09-28 16:29:36 +02:00
Amruth Pillai 0f934bd849 feat(ui): adopt Desk & Paper tokens, fonts, System theme and restyled primitives
Replace the achromatic shadcn palette with the Desk & Paper tokens (warm
neutrals, one moss accent, danger, warn and info), exposed to Tailwind
under their spec names; the previous names resolve to the new tokens
until every screen is rebuilt. Hard-coded palette classes become semantic
tokens and stage colors follow the spec.

Fonts move to Newsreader, Hanken Grotesk and JetBrains Mono. The theme
gains a System option that follows the operating system live, applied
before first paint, and Base UI now receives the locale's direction.

Primitives follow the component spec: button variants primary,
secondary, ghost, danger and link with a loading state, accent focus
rings on inputs, SwitchRow, semantic badges, segmented and underline
tabs, restyled menus, dialogs, sheets, tooltips and command bar, and a
single bottom-center toast with an Undo action. New: IconButton,
SegmentedControl, RadioGroup and NativeSelect.
2026-09-28 16:29:30 +02:00
Amruth Pillai 4485825dfe feat(ui): add a self-hosted Material Symbols icon subset
Icon renders Material Symbols Rounded at weight 300 from a subset font
that holds only the glyphs listed in packages/ui/src/icons/names.ts.
pnpm icons:build checks every name against Google's codepoints and
regenerates the font; a test keeps the manifest and the list in sync.
Icons are aria-hidden and untranslated, and directional ones mirror in
right-to-left layouts.
2026-09-28 16:29:17 +02:00
Amruth Pillai def4f72169 feat(pdf): map rendered header, section and item boxes
Templates tag the views that own the header, each section and each item
with data-resume-node. ResumeDocument's new onPageMap callback reads React
PDF's layout tree after each render and returns page-relative boxes, so the
editor can link lines on the page to entries in the panel. The attribute
stays on layout nodes and never reaches the PDF.
2026-09-28 16:01:16 +02:00
Amruth Pillai b0aecdfb5a docs: add Desk & Paper redesign plan
Plan for the UI redesign handoff: repo map, route changes, schema
migrations, component inventory, capability map, milestones and the
answered open questions. The handoff folder stays out of version control.
2026-09-28 16:01:15 +02:00
Amruth Pillai a7f1829484 ci: default to GitHub-hosted runners with opt-in Blacksmith
Workflows now run on GitHub-hosted runners unless the repository
variable USE_BLACKSMITH is "true", so forks work without setup. When
enabled, jobs run on Blacksmith runners (32 vCPU for build/test, 2 vCPU
for lightweight jobs) and use useblacksmith/checkout,
useblacksmith/setup-docker-builder, and useblacksmith/build-push-action.
Docker layer caches are keyed per architecture.

Replaces the CI_RUNNER_X64 and CI_RUNNER_ARM64 variables.
2026-09-28 09:01:00 +02:00
Amruth Pillai 328bf73cee chore(i18n): drop unregistered ckb-IR catalog
Crowdin shipped an empty Central Kurdish (ckb-IR) catalog with no translated
strings. The locale is not registered in the Lingui config or locale schema,
so remove the file and its PDF section title entry.
2026-09-28 08:59:38 +02:00
FalconSpyClaude Opus 5.5Amruth Pillaiautofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1b78e546e2 feat(applications): schedule interviews and view them on a calendar (#3539)
* feat(applications): schedule interviews and view them on a calendar

Interviews (screening, technical, behavioral, onsite, other) are stored as
"interview" entries on an application's activity timeline, so an application
can have any number of them and they show in its timeline without a
migration. Each interview has a start date-time (timezone-aware), duration,
and optional location and notes.

- schema: interview timeline entry type, interviewDetailsSchema, INTERVIEW_KINDS
- api: addInterview / updateInterview procedures (delete via timeline entry);
  generic timeline updates now only edit text on note entries
- web: Calendar view on the Applications page (month grid, type legend,
  upcoming list grouped by day, schedule button with application picker,
  per-day "+" and "+N more" popover), Interviews section and interview
  dialog in the application detail panel, interview rows in the timeline
  and CSV export
- mcp: add_application_interview / update_application_interview tools
- i18n: extract new strings into all locale catalogs (English fallback)
- docs: MCP tool table, scheduling guide section, resume-builder skill

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(applications): keep interview dates in local time and guard generic timeline edits

- Format the timeline date chip for interview entries in the viewer's local
  timezone so it matches the interview's date-time label; stage and note
  entries still render in UTC.
- Reject interview entries in the generic updateTimelineEntry path. A
  day-granular date edit kept the UTC time of day and could move an interview
  to the wrong local day; callers are pointed to updateInterview
  (update_application_interview). The MCP tool description now says so, and
  a service test covers the rejection.
- Associate each interview dialog label with its control via useId/htmlFor.
- Drop the duplicate onInput handler on the date-time input; onChange covers
  controlled inputs.
- Give the calendar's per-day schedule button an accessible name that
  includes the date, and update the extracted locale catalogs for the new
  message.

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-09-28 08:57:25 +02:00
Syed Ali Abbas ZaidiandAmruth Pillai fb756026fa feat(import): add LinkedIn data export as a resume import source (#3538)
* feat(import): add LinkedIn data export as a resume import source

LinkedIn's "Get a copy of your data" export ships a ZIP of per-topic
CSVs (Profile, Positions, Education, Skills, Languages,
Certifications). Reading these directly gives structured data without
needing a connected AI provider, unlike the existing PDF/DOCX import
path.

Also fixes a latent bug found while building this: parseJSONResume
(and the new LinkedIn parser) built their result via a shallow spread
of the shared `defaultResumeData` singleton, so assigning into
`result.sections.x` mutated that singleton in place and leaked section
data into the next unrelated import call in the same process. Both now
start from a structuredClone.

* fix(import): escape LinkedIn text, harden zip parsing and date handling

Move escapeHtml and toHtml from the plain-text importer into html.ts and
use them for LinkedIn summary, position descriptions and education notes,
so CSV text is HTML-escaped and line breaks become paragraphs or bullet
lists instead of collapsing into one run-on paragraph.

Only an empty end date now marks an entry as ongoing. Date cells that are
not "Mon YYYY" are kept verbatim, so a finished role with an unexpected
date format no longer reads as "Present".

Unzip only the six CSVs the importer reads, matched by exact file name,
and reject any of them larger than 5 MB. This avoids inflating the rest
of a complete LinkedIn export in the browser and stops Learning_Profile.csv
being read as Profile.csv.

Map LinkedIn's five language proficiency options onto levels 5 to 1,
falling back to parseLevel for anything else. Drop the literal BOM strip,
which TextDecoder already handles.

The import dialog no longer mentions an AI provider in the loading toast
for LinkedIn imports, which are parsed entirely in the browser.

Add a regression test for the JSON Resume importer leaking section data
through the shared defaultResumeData object, plus LinkedIn tests for HTML
escaping, unrecognised end dates, BOM headers, exact file name matching,
language levels and oversized entries.

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-09-28 08:57:20 +02:00
Lihan YANGAmruth Pillaiautofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
73e7a3cb6d fix(dev): make dotenvx available through pnpm (#3537)
* fix(dev): make dotenvx available through pnpm

* fix(dev): load local env from root scripts

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-09-28 08:57:14 +02:00
Amruth Pillai 685fcab605 fix(e2e): launch server directly so Playwright can stop it
pnpm 12.6 moves script children into their own process group. Playwright
stops its webServer with a process-group kill, so the server spawned via
`pnpm start` survived teardown and every E2E job hung until the 30 minute
timeout after all tests had passed.
2026-09-28 08:41:29 +02:00
Amruth Pillai 6db26e9b5c chore(pdf): regenerate section title catalog for ckb-IR locale 2026-09-28 08:07:15 +02:00
Amruth Pillai 2b31d70a8a chore: update translations 2026-09-28 07:44:52 +02:00
Amruth Pillai d0d20ce0fd chore(deps): upgrade dependencies
Bump workspace dependencies to their latest versions and dedupe the lockfile.

The upgrade left stale duplicates in pnpm-lock.yaml that broke the build and tests:

- @deepseek-ai/schemastery resolved to both 3.18.2 and 3.18.4. Both copies declare
  the global Schemastery namespace, so dsh-plugin's declaration emit failed with
  TS2883 on `Config`. `pnpm dedupe` collapses it to 3.18.4.
- vite's optional tsx peer resolved to 4.23.13 for importers without a direct tsx
  dependency and 4.23.15 elsewhere, producing two vitest 5.0.2 instances. Loading
  both in one run broke `expect(...).rejects`. Re-resolving tsx unifies the graph.
2026-09-28 00:23:21 +02:00
Amruth Pillai b48a9c2142 feat(web): refine motion system and simplify animated UI (#3546)
Audit every animation in the app and shared UI primitives against a
frequency-first motion bar: keyboard and high-frequency actions no longer
animate, remaining motion uses interruptible CSS transitions with shared
easing tokens, and redundant animation code is removed.

UI primitives (@reactive-resume/ui)
- Dialog, alert dialog, popover and tooltip move from tw-animate keyframes
  to Base UI data-starting/ending-style transitions; menus, popovers and
  tooltips skip motion when opened from the keyboard (data-instant).
- Dialog gains an `instant` prop; the command palette uses it.
- Accordion animates its real panel height; caret rotates instead of
  swapping icons.
- Menu backdrop blur moves onto the popup so it no longer snaps in after
  the fade; context menus and comboboxes fade only.
- Sidebar collapse uses the strong ease-out curve and snaps on Cmd+B.
- Toast, sheet, checkbox, tabs, toggle, inputs and message scroller get
  tokenised easing, correct transition properties and press feedback.
- Tabs no longer squeeze a trigger narrower than its label.
- Spinners keep spinning under prefers-reduced-motion.

Web app
- Remove the default route view transition and page-entrance slides.
- Add EASE_OUT_STRONG for Motion; replace built-in "easeOut" everywhere.
- Switch LazyMotion to domMax so layout and Reorder animations run.
- Builder: consolidate 12 section list files into one ItemsSection,
  opacity-only list rows with popLayout, instant Cmd+0, faster dock zoom,
  crossfade that no longer dips, transform-based progress bars.
- Dashboard: keep previous results while sorting/filtering, no empty-state
  flash, uncontrolled sidebar (no network round trip on collapse), calmer
  resume card tilt, no stacked hover wrappers.
- Settings: drop entrance/stagger wrappers and ActionButton.
- Agent: CSS marquee paused on hover; thread switches keep the layout.
- Homepage: fix invalid transition declarations, CSS spotlight drift,
  scroll-hiding header without a JS spring, tokenised curves.
- Theme switches change every color at once.
- Remove SSR-only useIsClient guards from the SPA.

Docs: rewrite the DESIGN.md animation section around the new tokens.
2026-09-27 17:10:42 +02:00
Amruth Pillai 0cb83602f5 fix(docker): create SeaweedFS bucket with aws-cli instead of minio/mc (#3544)
quay.io/minio/mc:latest is no longer publicly pullable (401 UNAUTHORIZED),
which broke the Docker publish workflow. Use the official amazon/aws-cli
image to create the bucket idempotently via head-bucket || s3 mb.
2026-09-26 10:25:04 +02:00
Amruth Pillai 712298843b chore(release): v5.3.2 (#3542) v5.3.2 2026-09-26 02:55:57 +02:00
Amruth Pillai 8c40313980 feat(deploy): support Vercel Hobby alongside Docker (#3541)
* feat(deploy): support Vercel Hobby alongside Docker

* fix(deploy): include PDFKit runtime font assets

* docs(deploy): document Vercel and Docker setup

* docs(deploy): record storage persistence checks

* refactor(deploy): drop scheduled staging cleanup

Staging uploads are deleted after finalization and expired ones are swept
on each new upload, so the Vercel cron job, its route, and CRON_SECRET are
no longer needed. The Deploy with Vercel wizard now asks for two secrets.

* docs(deploy): restructure Vercel guides

Split the Vercel page into a how-to with its environment reference, move the
large RPC staging protocol to an API reference page, and move CI deployment
checks to the contributing section. Point Deploy with Vercel buttons at main.

* chore: remove agent planning records and fix web app description

Delete superpowers plans/specs, ADRs, issue plans, execution briefs, domain
context maps, and Europass research. Describe apps/web as a TanStack Router
SPA served by apps/server.

* refactor(deploy): simplify Vercel support code

- Share one Redis client and key namespace through @reactive-resume/db/redis
  for API and auth instead of a second auth-only client.
- Drop the auth seeding retry; the provider already treats concurrent inserts
  as no-ops and deployment preparation seeds before runtime.
- Detect staging support from POST /api/storage/stage (404 on Docker) instead
  of a separate GET probe.
- Read staged bodies directly; the signed upload already caps their size.
- Close per-subscription Redis connections with disconnect() alone.
- Check Blob health with one list call instead of write/read/delete.
- Remove redundant tsdown onlyBundle list, dead namespace fallbacks, and the
  conditional spread in the health status.

* fix(deploy): heal stopped runs with dead owners and keep auth up without Redis

- Run owners refresh a Redis heartbeat until they release their claim. Stop
  requests reap the run immediately when the owner has stopped heartbeating,
  instead of leaving the thread blocked until the 15-minute TTL reaper.
- Auth and oRPC rate limiters fall back to per-instance memory limits when
  Redis errors, instead of rejecting every login or failing requests.

* ci: allow esbuild build for Vercel CLI and register deployment deps with knip

pnpm 12 fails dlx installs with ignored build scripts, so allow esbuild
explicitly. The server bundle keeps @vercel/blob, ioredis, and jose external,
and api/index.mjs is the Vercel Function entry.

* fix(web): send buffered RPC bodies instead of teed streams

Reading a request clone turned the original body into a stream, which
browsers send without inspectable request data and which needs duplex
mode. Send the already buffered Blob for direct requests.

* fix(web): send direct RPC bodies as bytes

Blob request bodies are sent as data pipes, so browser tooling cannot
inspect them. Buffer the original request as an ArrayBuffer and send those
bytes; this restores the e2e save assertions that match on request data.
2026-09-26 02:37:22 +02:00
Amruth Pillai 73ed3f9b03 chore(server): update version from 5.2.2 to 5.3.1 2026-09-23 00:12:42 +02:00
Lihan YANGandAmruth Pillai f0bc26cb3d fix(ci): restore Docker publishing with portable runner fallbacks (#3533)
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-09-22 17:07:28 +02:00
s3kfm 0ac320b0e9 fix(web): enabled drag and drop by moving file input on top of the button (#3529) 2026-09-22 14:32:34 +02:00
PerryLinkandAmruth Pillai d3131e0977 fix(import): reject out-of-range months that render as "undefined" (#3527)
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-09-21 19:47:02 +02:00
Santhi PrakashandAmruth Pillai 28d0170b05 fix(resume): detect section headings set in a side column (#3521)
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-09-21 19:46:46 +02:00
Santhi PrakashandAmruth Pillai ac69dd3f1a fix(server): verify migrated schema at startup (#3513)
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-09-21 19:46:36 +02:00
Amruth Pillai 3d4ae8679a Update Star History chart sources in README 2026-09-21 16:30:51 +02:00
Amruth Pillai 4fde62df6d chore: update dependencies 2026-09-19 22:05:55 +02:00
Amruth Pillai b5ff720f9d chore: update translations 2026-09-17 22:27:22 +02:00
Amruth Pillai b953435f2c fix: audit code for reduction 2026-09-17 22:16:44 +02:00
Amruth Pillai a30bf371ff docs: add IDEA.md as a symlink to AGENTS.md 2026-09-17 21:16:00 +02:00
Amruth Pillai 582a6fb429 fix(web): preserve dialogs opened during close animations
Opening another dialog during the previous dialog's 300 ms close animation could clear the new dialog and its close handler. This caused the post-merge dashboard lifecycle test to lose the Duplicate Resume dialog after renaming a resume.

- Scope delayed cleanup to the original dialog and require it to remain closed.
- Add regression coverage for both open and closing replacement dialogs; both cases failed before the fix and pass afterward.
- Include the fix in the v5.3.1 release notes.

Validation: `pnpm check`, `pnpm typecheck`, `pnpm test`, and the focused dialog-store suite (12 passing tests).
v5.3.1
2026-09-17 12:19:06 +02:00
Amruth Pillai 24d9e5fb5c chore: release v5.3.1
Prepare v5.3.1 with dashboard search and thumbnail improvements, PDF layout fixes, cover-letter integrations, and self-hosting updates.

- Bump the root version and add release notes with contributor credits, cover-letter REST migration instructions, and the new GHCR image path.
- Align the dashboard authentication plugin with Better Auth's fetch dependency to restore auth-client type inference.
- Regenerate the OpenAPI specification so published validation limits match runtime schemas.

Validation: `pnpm lingui:extract` (no missing translations), `pnpm check`, `pnpm typecheck`, and `pnpm test`.
2026-09-17 12:02:03 +02:00
Emanuele Tonello 2a2d08a8d2 fix(web): keep resume search local (#3510) 2026-09-17 00:14:42 +02:00
Emanuele TonelloandAmruth Pillai b42eb6ec06 fix: stop application search session refetches (#3507)
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-09-17 00:13:33 +02:00