Commit graph

529 commits

Author SHA1 Message Date
d6b4d79cf9 merge: bring CI fixes from main into freeze/v0.9.6/rc-2
Some checks failed
CI / Backend (Python) (push) Failing after 22s
CI / Frontend (Vue) (push) Successful in 21s
Mirror / mirror (push) Failing after 9s
Release / release (push) Failing after 4s
2026-07-07 22:27:07 -07:00
7f1b870abb ci: redirect /devl paths to /tmp for GitHub CI environment
Some checks failed
CI / Backend (Python) (push) Successful in 1m15s
CI / Frontend (Vue) (push) Successful in 20s
Mirror / mirror (push) Failing after 8s
2026-07-07 22:10:50 -07:00
e0346cfe6c ci: add ruff and pytest to pip install step on GitHub CI
Some checks failed
CI / Backend (Python) (push) Successful in 1m22s
CI / Frontend (Vue) (push) Successful in 24s
Mirror / mirror (push) Failing after 11s
2026-07-07 21:59:01 -07:00
874628ce24 ci: install libsqlcipher-dev before pip deps on GitHub CI
Some checks failed
CI / Backend (Python) (push) Successful in 1m23s
CI / Frontend (Vue) (push) Successful in 22s
Mirror / mirror (push) Failing after 8s
pysqlcipher3 is a C extension that links against libsqlcipher — not
present on ubuntu-latest by default. Mirrors what the Dockerfile already
does. backup.py uses it for encrypted DB export but never in CI tests.
2026-07-06 02:44:54 -07:00
6dcf6d0645 ci: install circuitforge-core before requirements.txt on GitHub CI
Some checks failed
CI / Backend (Python) (push) Successful in 1m18s
CI / Frontend (Vue) (push) Successful in 25s
Mirror / mirror (push) Failing after 8s
Matches snipe's pattern — pip resolves the git+ VCS dep more reliably
when it's pre-installed as a separate step rather than mixed into a
full requirements.txt solve.
2026-07-06 02:33:46 -07:00
201a867c60 Merge pull request 'fix(ci): restore green CI — ruff install + mirror secret rename' (#131) from fix/ci-workflows into main
Some checks failed
CI / Backend (Python) (push) Successful in 1m14s
CI / Frontend (Vue) (push) Successful in 21s
Mirror / mirror (push) Failing after 39s
2026-06-26 21:02:30 -07:00
380a20a6f8 fix(ci): restore TaskSpec re-export with noqa — tests import from here
All checks were successful
CI / Backend (Python) (push) Successful in 1m14s
CI / Frontend (Vue) (push) Successful in 20s
CI / Backend (Python) (pull_request) Successful in 1m20s
CI / Frontend (Vue) (pull_request) Successful in 20s
2026-06-26 20:55:52 -07:00
81e8a2f467 fix(lint): auto-fix 112 ruff F401/F541 errors in scripts and tests
Some checks failed
CI / Backend (Python) (push) Failing after 1m15s
CI / Frontend (Vue) (push) Successful in 20s
CI / Backend (Python) (pull_request) Failing after 1m15s
CI / Frontend (Vue) (pull_request) Successful in 20s
2026-06-26 20:52:42 -07:00
f20d671e42 fix(ci): remove dead db_path_obj variable; suppress E402 in dev-api.py
Some checks failed
CI / Backend (Python) (push) Failing after 23s
CI / Frontend (Vue) (push) Successful in 20s
CI / Backend (Python) (pull_request) Failing after 23s
CI / Frontend (Vue) (pull_request) Successful in 22s
2026-06-26 20:50:30 -07:00
b6f9cc2370 ci: add pyproject.toml with ruff config (exclude app/, suppress test noise)
Some checks failed
CI / Backend (Python) (push) Failing after 23s
CI / Frontend (Vue) (push) Successful in 20s
CI / Backend (Python) (pull_request) Failing after 23s
CI / Frontend (Vue) (pull_request) Successful in 20s
2026-06-26 20:46:56 -07:00
c15bcaba57 ci: retrigger after Docker network pool fix
Some checks failed
CI / Backend (Python) (push) Failing after 33s
CI / Frontend (Vue) (push) Successful in 27s
CI / Backend (Python) (pull_request) Failing after 22s
CI / Frontend (Vue) (pull_request) Successful in 19s
2026-06-26 20:41:26 -07:00
e225346d23 ci: retrigger after Docker network pool fix
Some checks failed
CI / Backend (Python) (push) Failing after 23s
CI / Frontend (Vue) (push) Successful in 21s
2026-06-26 20:41:18 -07:00
30423d7dd6 fix(ci): restore green CI — ruff install + mirror secret rename
Some checks failed
CI / Backend (Python) (push) Failing after 1s
CI / Frontend (Vue) (push) Failing after 1s
CI / Backend (Python) (pull_request) Failing after 1s
CI / Frontend (Vue) (pull_request) Failing after 1s
Two workflow fixes:
- ci.yml: add explicit `pip install ruff` before lint step; also add
  freeze/** to push trigger so RC branches run CI
- mirror.yml: rename GITHUB_MIRROR_TOKEN → GH_MIRROR_TOKEN to match
  org-level secret; Forgejo reserves the GITHUB_* prefix so that name
  was silently shadowed, causing mirror pushes to fail with auth errors
2026-06-26 19:25:10 -07:00
bfb6de0dfe ci: add freeze/** branches to CI trigger
Some checks failed
CI / Backend (Python) (push) Failing after 15s
CI / Frontend (Vue) (push) Failing after 1s
freeze/rc branches were not covered by the push trigger, leaving
RC-stage work untested. Adds 'freeze/**' alongside existing patterns.
2026-06-26 19:24:40 -07:00
82c26074d8 fix: search prefs wizard data loss, resume sync link, docs + GUI help links
Bug fixes (filed as #125–#128):
- Wizard step 7 read data.titles instead of data.search.titles — user-entered
  job titles and locations were silently dropped on every wizard run (#125)
- GET /api/settings/search returned "titles" key but store expected "job_titles" —
  Settings → Search Prefs always showed empty even when data existed (#126)
- remote_only preference not persisted during wizard setup (#127)
- apply-to-profile didn't set default_resume_id in user.yaml, so future
  Resume Profile saves never synced back to the library entry (#128)

Also:
- Wizard step headings corrected (off-by-one after Training step was inserted)
- Ollama host in wizard inference step now reads from saved wizard state
- Resume upload during wizard now creates a library entry and sets it as default

Docs:
- New: docs/user-guide/daily-workflow.md — end-to-end daily usage guide
- Updated: docs/user-guide/settings.md — rewritten for Vue SPA (was Streamlit)
- mkdocs.yml nav: Daily Workflow added as first User Guide entry

GUI help links:
- web/src/composables/useDocsUrl.ts — shared docs base URL composable
- Home: "Daily Workflow guide ↗" link in subtitle
- Job Review: "? Docs" link in title row
- Resume Library: "? Help" link in header
- Settings → Resume Profile: "? Help" link in page header
- Settings → Search Prefs: "? Help" link in page header
2026-06-15 16:52:56 -07:00
f799aff4e0 fix: CPU as default inference profile, remote last in list
- Reorder PROFILES in step_hardware.py, _WIZARD_PROFILES in dev-api.py,
  and <option> elements in WizardHardwareStep.vue: cpu → single-gpu → dual-gpu → cf-orch → remote
- _suggest_profile() now defaults to "cpu" instead of "remote" when no local GPUs detected
- Update no-GPU hint text to remove "Remote" from suggested options
- Add nvidia GPU device reservation to compose.wizard-test.yml so the
  wizard test instance can run nvidia-smi and detect host GPUs
- Switch wizard-test compose to use ghcr.io/circuitforgellc/peregrine:latest
  (same image as main compose, avoids stale peregrine-api tag drift)
2026-06-15 09:11:14 -07:00
7e361aa6d1 chore: release Dockerfile and GHCR publish workflow for RC1
- Replace stale Streamlit Dockerfile with self-contained release build
  (uvicorn/FastAPI; Streamlit removed in #104)
- cf-orch BSL client installed via BuildKit secret in release CI;
  community builds skip it gracefully and fall back to local backends
- compose.yml api build now uses single-repo context (context: .)
  so self-hosters can build without sibling repo setup
- Add image: tags to api + web services in compose.yml and compose.demo.yml
  so docker compose pull works for pre-built images
- Enable Docker push in release.yml: api + web to GHCR on v* tags
  (was disabled pending BSL registry policy — cf-agents#3 resolved)
- cloud image (compose.cloud.yml / Dockerfile.cfcore) unchanged:
  never published, built on Heimdall with sibling repos available
- .dockerignore: add plain_text_resume.yaml and adzuna.yaml
2026-06-14 20:03:40 -07:00
80041d1dd9 feat: wire cf-orch allocate flow for LLM routing
- Fix cf_text base_url (was port 8006/cf-musicgen, corrected to 8008/cf-text)
- Add cf_orch blocks to cf_text, ollama, ollama_research, vllm_research backends
- Fix ollama_research base_url to host.docker.internal:11435 (was Docker service name)
- Promote cf_text to top of research_fallback_order
- Add cf_text backend to llm.cloud.yaml with cf_orch block
- Wire _RL_WIZARD rate limit to wizard_ai_interview endpoint (closes TODO from #122)

Closes: #122
2026-06-14 15:21:53 -07:00
b3435a8bd8 fix: add slowapi to requirements.txt for Docker image
slowapi was only in environment.yml (conda env) but missing from
requirements.txt, causing ModuleNotFoundError in the Docker container.
2026-06-14 14:13:12 -07:00
e85fb9bba3 test: fix rate limiter cross-test contamination
Each importlib.reload(dev_api) re-applies @limiter.limit() decorators to
the shared slowapi Limiter singleton, accumulating stale registrations in
_route_limits. One real HTTP request then triggered N limit-checks (N =
reload count), exhausting per-hour budgets prematurely.

Fix: conftest.py autouse fixture resets both _storage and _route_limits
before each test, giving a clean slate regardless of prior reloads.

Also updates test_dev_api_prep.py client fixture to use monkeypatch to
clear DEMO_MODE + importlib.reload to get a fresh IS_DEMO module state
(prevents 403 bleed from test_demo_guard.py tests running first).

All 842 tests passing.
2026-06-14 14:00:31 -07:00
88b6943527 merge: feat/122-rate-limiting into freeze/rc-1
Per-user LLM rate limiting via slowapi: cloud-aware key function,
4 endpoint limits, demo bypass, SSRF and path traversal already in
fix/ci-ruff-lint merge.

Closes: #122
2026-06-14 12:41:18 -07:00
71e8eeb090 merge: feat/77-ai-wizard into freeze/rc-1
AI profile wizard full implementation: backend interview endpoints, BYOK
tier flag, chat UI, store actions (skip/keepChatting), settings CTA,
quality review fixes.

Closes: #77
2026-06-14 12:16:49 -07:00
6db1fe1546 merge: fix/ci-ruff-lint into freeze/rc-1
CI lint fixes, CVE security mitigations, sync status UI (#120),
bugbot Forgejo token fallback (#118), npm audit, mnemo compose stub.
2026-06-14 12:16:40 -07:00
b13abb1118 feat(settings): sync status UI (#120) + bugbot Forgejo token fallback (#118)
Issue #120 — sync status panel in DataView:
- Add SyncStore (web/src/stores/settings/sync.ts) to track last-sync
  timestamp, in-progress state, and error message for profile/preferences
- Extend DataView with a sync status section: last synced time, refresh
  button, error display, and per-section progress indicators

Issue #118 — bugbot Forgejo token fallback:
- scripts/feedback_api.py: try FORGEJO_BOT_TOKEN first, then fall back to
  FORGEJO_TOKEN so ops can provision a dedicated cf-bugbot account without
  breaking existing single-token installs

Add FORGEJO_BOT_TOKEN and LLM_RATE_* env var documentation to .env.example

Closes: #120
Closes: #118
2026-06-14 12:16:16 -07:00
3cdd14c345 fix(security): CVE mitigations — path traversal, SSRF, dep upgrades, npm audit
Path traversal (cloud middleware):
- Add _VALID_USER_ID_RE UUID regex; reject non-UUID user_id before
  constructing db path from CLOUD_DATA_ROOT / user_id / ...
- Non-UUID values log a warning and fall through to unauthenticated path

SSRF (test_email IMAP endpoint):
- Add _is_ssrf_host() using ipaddress + socket.gethostbyname()
- Checks resolved IP against RFC-1918, loopback, and link-local ranges
- Fails closed on DNS resolution errors (returns True = blocked)

Dependency security pins in environment.yml (transitive CVEs):
- starlette>=1.0.1 (PYSEC-2026-161), python-multipart>=0.0.27 (CVE-2026-40347),
  aiohttp>=3.14.0, tornado>=6.5.5, cryptography>=46.0.7, langsmith>=0.8.0,
  gitpython>=3.1.50, lxml>=6.1.0, idna>=3.15, markdownify>=0.14.1
- Direct dep upgrades: requests>=2.33.0, pypdf>=6.12.0, python-dotenv>=1.2.2,
  PyJWT>=2.13.0, curl_cffi>=0.15.0

npm audit (web/package-lock.json):
- Resolved 7 of 9 CVEs; 2 remaining esbuild CVEs require vite 8 upgrade
  (tracked as issue #123 — breaking change, deferred)
2026-06-14 12:16:00 -07:00
ad27467026 chore(infra): add mnemo service stub to compose.yml
Pre-existing local development addition — mnemo vector memory service
placeholder for future integration work.
2026-06-14 12:15:16 -07:00
d801650db1 feat(api): per-user LLM rate limiting via slowapi
Add scripts/rate_limit.py with cloud-aware key function:
- In cloud mode, extracts user_id from _request_db ContextVar path (part[-3])
  so each cloud user has their own rate limit bucket
- In demo mode, returns unique per-request key to disable limiting entirely
  (_demo_guard handles write-blocking; rate limiting would block the demo UX)
- Falls back to client IP for local/self-hosted installs

Wire limiter to 4 endpoints with conservative per-user limits:
- POST /generate/cover-letter: 20/hour
- POST /research/run: 10/hour
- POST /qa/suggest: 60/hour
- POST /survey/analyze: 30/hour

Add _demo_guard() to generate_research and suggest_qa_answer (was missing).
Fix pre-existing silent except in suggest_qa_answer: was bare except pass,
now logs warning with exc_info.

Add _RL_WIZARD placeholder constant with TODO to wire to wizard/ai/interview
after feat/77 merges (declared but intentionally not applied yet to avoid
false sense of security — comment makes the gap explicit).

18 tests covering cloud user isolation, demo bypass, IP fallback, all 4
endpoints returning 429 on excess, retry_after header, and demo guard.

Closes: #122
2026-06-14 12:14:21 -07:00
eebfc84a80 fix(wizard): quality review fixes — store encapsulation + skip action + settings CTA
- Add keepChatting() action to aiInterview store; replace direct store.complete = false
  mutation in WizardAIView template with store.keepChatting()
- Add skip() action wrapping SKIP_SIGNAL constant; replace magic string store.send('skip')
  with store.skip()
- Fix skip button disabled condition to include || store.complete (was always enabled
  when wizard was complete, allowing spurious skip after finalize)
- Add _persist() call after user bubble append in send() so localStorage draft is
  written before the async fetch — prevents stale draft on browser refresh during
  slow LLM call
- Fix @click="store.startOver" → @click="store.startOver()" (missing parentheses)
- Add 2 tests: skip() sends SKIP_SIGNAL, keepChatting() clears complete without reset
- Remove 'ultra' from Tier type in appConfig.ts (violates no-ultra-tier policy)
- Add MyProfileView wizard callout banner with tier-aware unlock/upgrade CTAs
- Add clarifying comment on wizard route guard in router/index.ts

Closes: #77
2026-06-14 12:13:58 -07:00
cecf85de02 feat(wizard): AI interview store, WizardAIView chat UI, byokUnlocked in appConfig 2026-06-13 20:10:38 -07:00
e9943908c6 fix(wizard): 503 on LLM error, sanitize history content, typed HistoryMessage model 2026-06-13 20:04:14 -07:00
6d1edff1b9 fix(wizard): inject profile_so_far context into AI interview LLM prompt 2026-06-13 19:59:58 -07:00
6327a4cdd9 feat(wizard): backend AI interview endpoints + BYOK tier flag 2026-06-13 19:57:00 -07:00
3048d8e2f4 docs: add LLM development disclosure to README
All checks were successful
CI / Backend (Python) (push) Successful in 1m35s
CI / Frontend (Vue) (push) Successful in 23s
Humans own design, architecture, code review, testing, and
verification. LLMs are part of our development workflow.
Links to circuitforge.tech/positions for our full position.
2026-05-28 08:20:16 -07:00
02d79e6727 fix(ci): install ruff before lint step
All checks were successful
CI / Backend (Python) (push) Successful in 1m33s
CI / Frontend (Vue) (push) Successful in 19s
CI / Backend (Python) (pull_request) Successful in 1m21s
CI / Frontend (Vue) (pull_request) Successful in 19s
ruff is not in requirements.txt (dev-only tool) so the CI runner
couldn't find it. Install explicitly in the workflow.
2026-05-21 12:03:46 -07:00
e4c5744d87 fix(ci): restore TaskSpec re-export in task_scheduler.py
Some checks failed
CI / Backend (Python) (push) Failing after 31s
CI / Frontend (Vue) (push) Successful in 22s
CI / Backend (Python) (pull_request) Failing after 23s
CI / Frontend (Vue) (pull_request) Successful in 20s
ruff --fix removed the TaskSpec import as unused within the module,
but it is part of the public API — tests import it from scripts.task_scheduler
rather than reaching into circuitforge_core directly.
Add # noqa: F401 to protect intentional re-exports from future auto-fix.
2026-05-21 11:51:40 -07:00
46bae7db1c fix(ci): rename GITHUB_MIRROR_TOKEN secret to GH_MIRROR_TOKEN
Some checks failed
CI / Backend (Python) (push) Failing after 26s
CI / Frontend (Vue) (push) Successful in 22s
CI / Backend (Python) (pull_request) Failing after 22s
CI / Frontend (Vue) (pull_request) Successful in 20s
Forgejo reserves the GITHUB_* prefix for secret names — creating a secret
called GITHUB_MIRROR_TOKEN returns 'invalid secret name'.
Also rename the GITHUB_TOKEN step env var to GH_MIRROR_PAT to avoid
collision with the built-in Forgejo Actions context variable.
2026-05-21 11:41:11 -07:00
e87c707dd9 chore(lint): ruff auto-fix unused imports in tests/
Some checks failed
CI / Backend (Python) (push) Failing after 30s
CI / Frontend (Vue) (push) Successful in 22s
CI / Backend (Python) (pull_request) Failing after 27s
CI / Frontend (Vue) (pull_request) Successful in 20s
Removes unused imports flagged by ruff F401 across 47 test files.
Auto-fix only — imports verified unused by static analysis.
2026-05-20 23:07:52 -07:00
7dcdf551fc chore(lint): ruff auto-fix unused imports in scripts/ and scrapers/
Removes unused imports flagged by ruff F401 across 12 scripts.
All removals are safe — ruff only auto-fixes imports that are verifiably unused.
2026-05-20 23:07:26 -07:00
544a6aeeb3 fix(ci): add ruff config, clean lint in dev-api.py + scripts
- Add pyproject.toml with ruff per-file-ignores:
  - Exclude deprecated app/ Streamlit dir entirely
  - Suppress E702 in dev-api.py (intentional compact Pydantic models)
  - Suppress E402 in finetune_local.py (conditional ML imports after CUDA check)
  - Suppress F841/E741/E702 in tests/ (mock-patch capture pattern)
- Remove unused db_path_obj assignment in dev-api.py:760
- Add # noqa: E402 to documented mid-file imports in dev-api.py
- Rename ambiguous l variable to line/lbl in finetune_local.py + label_tool.py
2026-05-20 23:06:49 -07:00
2051880d73 fix: dark mode CSS token gaps, interview score display, undefined CSS vars
Some checks failed
CI / Backend (Python) (push) Failing after 39s
CI / Frontend (Vue) (push) Successful in 21s
Mirror / mirror (push) Failing after 10s
InterviewCard: remove erroneous *100 multiplier from scoreClass and
scoreLabel — match_score is stored as 0-100 in the DB, not 0-1. This
was producing scores like '1490%' for jobs with a 14.9 raw score.

peregrine.css: define --color-hover token for light (rgba(0,0,0,0.06))
and dark (rgba(255,255,255,0.07)). Was undefined, leaving hover states
on InterviewCard, InterviewsView, ReferencesView, ContactsView silent.

InterviewCard + InterviewsView: replace var(--color-primary-muted,#e8f0ff)
with var(--app-primary-light). The hardcoded #e8f0ff fallback is a bright
light-blue that renders on dark backgrounds when the variable is undefined.

WizardTrainingStep: --font-sans → --font-body (correct token name).

ResumeSyncConfirmModal, ResumeLibraryCard, ResumeOptimizerPanel,
resume-review sub-pages: --font-sm → --text-sm across all occurrences.
--font-sm was never defined; most had a 0.875rem fallback (which matches
--text-sm) but the correct token should be referenced directly.
2026-05-18 13:37:08 -07:00
7d1b1319be docs: fix repo URLs and clarify BYOK tier unlocking in feature matrix
Replace git.circuitforge.io/circuitforge/peregrine with the correct
Forgejo URL (git.opensourcesolarpunk.com/Circuit-Forge/peregrine) in
Quick Start, License, and Contributing clone instructions.

Update feature matrix in docs/index.md to show BYOK‡ for AI features
(cover letter, company research, interview prep, survey assistant) with
a footnote explaining the free-with-own-backend model. Previously the
table showed these as Paid-only, which would mislead self-hosters.
2026-05-18 12:05:03 -07:00
b44a7975bc fix(ci): restore green CI — libsqlcipher-dev, prep/survey test drift
Some checks failed
CI / Backend (Python) (push) Failing after 2m25s
CI / Frontend (Vue) (push) Successful in 24s
Mirror / mirror (push) Failing after 8s
Release / release (push) Failing after 4s
Backend: add apt-get install libsqlcipher-dev before pip install so
pysqlcipher3 builds in the runner image.

Frontend: prep.test.ts was missing a qa mock (fetchFor now calls 5
endpoints in parallel; tests only mocked 4 — 5th returned undefined,
threw in catch, research.value never set). survey.test.ts: analyze()
was refactored from sync-result to async-task+poll; update test to
mock POST then poll completion.

Also remove Classic UI (Streamlit) button from AppNav — Streamlit is
deprecated and the button caused an unrecoverable redirect loop.
2026-05-17 21:50:35 -07:00
0d6ddd35cf feat(config): GPU_SERVER_URL + cf-orch task-routed backends
- Rename user-facing env var CF_ORCH_URL → GPU_SERVER_URL with full
  backward-compat alias (closes #116). Priority chain: GPU_SERVER_URL
  → CF_ORCH_URL → orch.circuitforge.tech when CF_LICENSE_KEY present.
  Write-back to os.environ[CF_ORCH_URL] keeps all downstream callers
  unchanged.
- Add four task-routed llm.yaml backends (cf_cover_letter, cf_ats_rewrite,
  cf_job_research, cf_interview_prep) using cf_orch.product + cf_orch.task.
  Coordinator resolves model/node from assignments.yaml (closes #115).
- Update compose.yml, compose.cloud.yml, compose.test-cfcore.yml,
  .env.example to use GPU_SERVER_URL as primary documented var.
2026-05-17 20:16:40 -07:00
5c4992dbeb docs: bump version badge to match latest Forgejo release
Some checks failed
CI / Backend (Python) (push) Failing after 1m24s
CI / Frontend (Vue) (push) Failing after 21s
Mirror / mirror (push) Failing after 7s
2026-05-17 11:19:13 -07:00
fc3bd8859e docs: document Gotcha #14 (body over html), retake screenshots for light theme
Some checks failed
CI / Backend (Python) (push) Failing after 1m11s
CI / Frontend (Vue) (push) Failing after 20s
Mirror / mirror (push) Failing after 8s
2026-05-08 15:49:47 -07:00
73132222a2 fix: dark/explicit themes now show correct page background
Some checks failed
CI / Backend (Python) (push) Failing after 1m14s
CI / Frontend (Vue) (push) Failing after 19s
Mirror / mirror (push) Failing after 7s
Release / release (push) Failing after 4s
index.html set 'html, body { background: #eaeff8 }' hardcoded.
body paints on top of html — even with html correctly going dark
via CSS variable resolution, the hardcoded body background covered it.

Fix:
- Remove body background from inline style (body is now transparent)
- Add blocking script to read cf-theme/cf-hacker-mode from localStorage
  and set data-theme on <html> before first paint (FOUT prevention)
- Add html[data-theme='dark'|'solarized-dark'|'hacker'] rules so the
  correct background fires immediately on initial load for all themes
2026-05-08 15:44:33 -07:00
293f0aba53 chore(release): v0.9.4
Some checks failed
CI / Backend (Python) (push) Failing after 2m10s
CI / Frontend (Vue) (push) Failing after 57s
Mirror / mirror (push) Failing after 8s
Release / release (push) Failing after 3s
Messaging overhaul: expandable email timeline with lazy body loading,
sticky compose bar replacing always-visible action buttons, layout height
fixed to 100dvh. Accessibility fixes for contrast failures on orange/amber
backgrounds. Theme-aware replacements for hardcoded colors in Interviews,
References, and JobReview. Indeed alert parser, Oracle HCM scraper,
manage.sh compose engine detection.
2026-05-08 13:32:10 -07:00
5d185650d9 docs(screenshots): retake all four views after CSS theme fix — consistent light theme throughout
Some checks failed
CI / Backend (Python) (push) Failing after 1m11s
CI / Frontend (Vue) (push) Failing after 22s
Mirror / mirror (push) Failing after 7s
2026-05-06 09:58:33 -07:00
6ae9fa62fe docs(readme): landing page rewrite — centered logo, feature table, BYOK explanation, Forgejo-primary note, split license table
Some checks failed
CI / Backend (Python) (push) Failing after 1m11s
CI / Frontend (Vue) (push) Failing after 19s
Mirror / mirror (push) Failing after 7s
2026-05-06 08:51:28 -07:00
5d8018ef40 fix(theme): scope dark media override to auto mode only
Some checks failed
CI / Backend (Python) (push) Failing after 1m32s
CI / Frontend (Vue) (push) Failing after 25s
Mirror / mirror (push) Failing after 7s
Release / release (push) Failing after 6s
peregrine.css used :root:not([data-theme="hacker"]) in the
prefers-color-scheme:dark block, causing --app-primary-light and
--app-accent-light to resolve to dark navy/brown in every explicit
light theme (light, solarized-light, colorblind) on dark-OS machines.

Changed to :root:not([data-theme]) to match theme.css's pattern,
so the media query only fires in auto mode. Explicit [data-theme="dark"]
block handles the dark-theme-on-light-OS case unchanged.

Also fixed incorrect fallback values in HintChip.vue (#0d1829 → #eaeff8)
and App.vue global toast (#2a3650/#eaeff8 → light-mode values).

Closes: dark elements in light themes on dark-OS machines
2026-05-05 14:22:59 -07:00