- Add remote/orchestrator filter by workplace (remote, not remote, unknown) with URL param
- Expose isRemote on job list API; canonicalize URLs and source_job_id dedup on import
- Onboarding: optional VITE_SKIP_RXRESUME_ONBOARDING for RxResume-free onboarding
- Scoring UI + docs for company skip list; pipeline-run dedup note
- Vitest: TZ=UTC for stable time-based tests
- DEPLOY_GITEA_VM_CRON_TELEGRAM.md for VM/cron/Telegram ops
Made-with: Cursor
Turn Ghostwriter's flat message list into a tree structure, enabling
Claude.ai/ChatGPT-style branching conversations.
**Data model**: Add `parentMessageId` and `activeChildId` to messages,
`activeRootMessageId` to threads. Migration backfills existing messages
into a linear chain and links regenerated messages as siblings.
**Backend**: Tree-walking queries (getActivePathFromRoot, getAncestorPath,
getSiblingsOf), rewritten history builder that follows the ancestor path,
new editMessage and switchBranch services, regenerate now works on any
assistant message (not just the latest).
**Frontend**: BranchNavigator component (← 2/3 → arrows), inline edit on
user messages, per-message regenerate on assistant messages, regenerate
button removed from composer (now per-message).
**Infra**: Pin Node 22 via Volta to prevent ABI mismatches with
better-sqlite3 across environments.
* Add startup.jobs extractor support
* Harden startup.jobs extractor inputs
* Wire startupjobs into Docker and CI
* Tighten startupjobs review follow-ups
* fix: publish ghcr during release workflow
* feat: add startupjobs max jobs configuration and update related tests
* Add RxResume URL setting to dashboard
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Add language settings for AI-generated resume output
* Resolve merge conflicts for language settings PR
* Fix language settings review feedback and CI lint
* Tighten language setting precedence and onboarding validation
---------
Co-authored-by: saad <Saad>
* initial
* lint fix
* docs!
* fix CI
* ci and runner fix
* fix + docs!
* make CI pass
* country specific search
* remove country specific language
* fix UI
* address comments
* Address visa sponsor PR feedback
* Address remaining visa sponsor review feedback
* Harden visa sponsor provider validation
* feat(settings): add rxresume mode and v5 api key settings
* feat(server): add mode-aware rxresume adapter with auto v5-first selection
* refactor(server): route settings profile and pdf generation through rxresume adapter
* feat(api): support rxresume v4/v5 in onboarding and settings routes with ok/meta responses
* feat(client): add rxresume mode selector and v5 api key setup flow
* docs: document rxresume auto mode with v5-first self-hosted setup
* test: verify dual-mode rxresume support and ci parity checks
* comments
* services folder
* correct types for v5
* tests and docs fix
* Fix RxResume auto fallback and route API consistency
* warning for both being set
* simpler response
* onboarding component improvements, v5 check still not working
* fix list resume endpoint...
* fix api endpoints to latest v5 docs
* don't show the entire project field on v5
* remove auto entirely
* formatting
* ci green
* v5 has a different resume schema
* remove redundant check
* remove requirement that only one must be specified
* consolidate sections
* base resume can be v4 or v5
* saving now works
* status indicator
* actually render some pills
* reason for failure
* fix apikey verification
* dedupe isValidatingMode
* reefactoor
* simplification?
* refactor?
* ci passing
* remove auto from docs
* tailoring is schema dependent
* skills object tighter
* remove redundant text
* fix lint
* mode
* Deduplicate string cleanup helpers and not-found responses
* Enforce aliased imports for infra and shared modules
* Enforce @client/@server aliases for deep relative imports
* Deduplicate visa sponsor and location filter definitions
* Use shared city filter export in extractor location checks
* chore: move @types/canvas-confetti to devDependencies, remove unused get-tsconfig direct dep
* chore: configure knip with workspace entry points for all packages
* refactor(shared): split 1119-line types.ts into domain modules under types/
* refactor: remove llm-service.ts shim, migrate all import sites to llm/service directly
* refactor(settings): migrate 4 manually-resolved settings into conversion registry
* refactor: split gmail-sync.ts into gmail-api, email-router, and thin orchestrator
* refactor(orchestrator): extract useKeyboardShortcuts and usePipelineControls from OrchestratorPage
Splits the 840-line OrchestratorPage into a thin orchestration shell (~480 lines) by
extracting keyboard shortcut handling into useKeyboardShortcuts.ts and pipeline
control logic into usePipelineControls.ts. Net negative line count across all files.
* feat: create settings registry (Step 1)
Introduces a single source of truth for all settings, combining schema definitions, default logic, parsing, and serialization into a single configuration object.
* feat: derive schema, keys, and types from settings registry (Step 2)
Derives AppSettings nested shape, SettingKey DB union, and updateSettingsSchema Zod shape automatically from the settings registry.
* refactor: gut envSettings and remove settings-conversion (Step 3)
Replaces manual env arrays with registry-driven maps in envSettings.ts.
Deletes settings-conversion.ts since all parsing/defaults now live in the registry.
* refactor: simplify getEffectiveSettings with generic loop (Step 4)
Replaces ~334 lines of manual key-by-key unpacking with a generic registry-driven iteration loop (~40 lines). Models, typed, string, and virtual kinds are automatically derived.
* refactor: simplify settingsUpdateRegistry (Step 5)
Replaces ~350 lines of explicit per-key update handlers with a dynamic generic loop over the settings registry, properly routing persistence and side effects.
* refactor(settings): implement nested settings registry and clean up tests
- Migrate settings system to use a centralized nested registry (`settings-schema.ts`, `registry.ts`)
- Remove obsolete flat-to-nested conversion logic (`settings-conversion.ts`)
- Address Biome warnings by explicitly ignoring intentional `any` usage in generic runtime schema builder and registry logic
- Clean up unused variables in test files (`SettingsPage.test.tsx`) to achieve a 100% green CI pipeline
* refactor(settings): address PR comments on env data and registry parsing
- Narrow `getEnvSettingsData` return type to `Partial<AppSettings>` to satisfy strict typing and omit 'typed' registry entries
- Introduce `parseNonEmptyStringOrNull` for typed string settings so empty-string overrides cleanly fall back to defaults (matching original `||` logic)
- Add missing unit tests for registry parse/serialize helpers (JSON, bools, numeric clamping)
* initial change
* nav highlighting
* icon change
* deeeedoooop
* text
* show version number on all pages
* icon
* remove unused code
* add knip
* formatting
* remove unused code
* types fix
* remove notion completely from the codebase.
* update test for new url structure
* clean up the fucking shop boys
* make a "create job" factory and use that
* moar factories
* formatting
* feat(shared): add glassdoor to job source model
* feat(jobspy): support glassdoor site in scraper and discovery
* feat(pipeline): include glassdoor in source selection and API schema
* feat(ui): add glassdoor toggle to jobspy settings and run estimates
* test/docs: cover glassdoor jobspy integration end-to-end
* fix(jobspy): make glassdoor always-on without settings toggle
* fix(jobspy): fallback glassdoor when location is country-level
* refactor(jobspy): drop direct pandas usage in wrapper
* feat(pipeline): gate glassdoor by supported countries
* fix(jobspy): restore pandas output and keep glassdoor disable copy
* fix(jobspy): map country-level glassdoor searches to city fallbacks
* feat(ui): require glassdoor city for country-level runs
* api(jobs): normalize PATCH /jobs/:id response contract and error mapping
* api(jobs): support core job detail edits in update schema
* feat(client): add JobDetailsEditDrawer with core metadata form
* feat(orchestrator): open edit drawer from JobDetailPanel more actions
* feat(orchestrator): add edit drawer trigger to ready and discovered more actions
* feat(api): add lightweight jobs list view without pagination
* refactor(client): use lightweight jobs list and on-demand job detail
* refactor(ui): separate job list rows from full job detail
* perf(home): reduce jobs payload to applied lightweight rows
* perf(db): add safe composite index for jobs list queries
* feat(api): default jobs endpoint to lightweight list view
* style: apply biome formatting for jobs list-view changes
* feat(api): add jobs revision endpoint for lightweight change detection
* refactor(client): switch jobs auto-refresh to revision checks
* perf(client): drive pipeline freshness via sse with polling fallback
* refactor(orchestrator): remove pipeline status polling loop from page
* chore(client): add periodic safety refresh and refresh lifecycle hardening
* refactor(types): define JobListItem via Pick<Job> to prevent drift
* feat(shared): centralize supported country list and source-country rules
* feat(orchestrator): add country selector and UK-only source gating in automatic run modal
* feat(orchestrator): persist country selection and run only compatible extractors
* fix(pipeline): enforce country-source compatibility during discovery
* test(orchestrator): cover country-based source gating and pipeline enforcement
* formatting
* test fix
* lint
* comments
* prevent auto focus grab
* verification
* command and popover
* make sure scroll is working