Commit graph

91 commits

Author SHA1 Message Date
5a4216952f fix: auto-configure git safe.directory in setup.sh for /opt-style installs
Git 2.35.2+ rejects repos where directory owner != current user, which
is the common case when cloned as root into /opt. setup.sh now detects
this and calls git config --global --add safe.directory automatically.
When run via sudo, it writes into SUDO_USER's config rather than root's.
README updated with both fixes: git safe.directory and chown for preflight.
2026-02-26 22:07:39 -08:00
278884d6b8 docs: add install notes for /opt ownership, Podman rootless, Docker group 2026-02-26 21:15:42 -08:00
1abea34752 fix: skip --profile for remote profile; fixes podman-compose compat
podman-compose 1.0.6 has no --profile flag, causing a fatal parse error.
'remote' profile means base services only — no service in compose.yml is
tagged 'remote', so --profile remote was always a no-op with Docker too.
Introduce PROFILE_ARG that only adds --profile for cpu/gpu profiles where
it actually activates optional services.
2026-02-26 21:12:12 -08:00
2c3544ad50 fix: render banner link as clickable page_link instead of italic text 2026-02-26 20:53:54 -08:00
ab5750d5fc fix: install make in setup.sh; guard manage.sh against missing make
setup.sh now installs make (via apt/dnf/pacman/brew) before git and
Docker so that manage.sh commands work out of the box on minimal server
installs. manage.sh adds a preflight guard that catches a missing make
early and redirects the user to ./manage.sh setup. Also fixes the
post-setup next-steps hint to use ./manage.sh instead of bare make.
2026-02-26 20:51:34 -08:00
630b2cad41 feat: show version tag in sidebar footer 2026-02-26 14:39:47 -08:00
22598edff6 feat: multiselect tags for job titles & locations; remove duplicate Notion section; docker detection for services panel
- Job titles and locations: replaced text_area with st.multiselect + + add button + paste-list expander
-  Suggest now populates the titles dropdown (not auto-selected) — user picks what they want
- Suggested exclusions still use click-to-add chip buttons
- Removed duplicate Notion expander from System Settings (handled by Integrations tab)
- Services panel: show host terminal copy-paste command when docker CLI unavailable (app runs inside container)
2026-02-26 14:26:58 -08:00
d593d23fdd fix: add address field to Resume Profile — was hidden, triggering false FILL_IN banner 2026-02-26 14:03:55 -08:00
f57dca265f fix: port drift on restart — down before preflight, read port from .env
Makefile restart target now runs compose down before preflight so ports
are free when preflight assigns them; previously preflight ran first while
the old container still held 8502, causing it to bump to 8503.

manage.sh start/restart/open now read STREAMLIT_PORT from .env instead
of re-running preflight after startup (which would see the live container
and bump the reported port again).
2026-02-26 13:57:12 -08:00
24a108afc7 feat: resume upload in Settings + improved config hints
- Resume Profile tab: upload widget replaces error+stop when YAML missing;
  collapsed "Replace Resume" expander when profile exists; saves parsed
  data and raw text (for LLM context) in one step
- FILL_IN banner with clickable link to Setup wizard when incomplete fields detected
- Ollama not reachable hint references Services section below
- Fine-tune hint clarifies "My Profile tab above" with inference profile names
- vLLM no-models hint links to Fine-Tune tab
2026-02-26 13:53:01 -08:00
29f38cec64 refactor: replace sidebar LLM generate panel with inline field buttons
Removed the dropdown-based sidebar panel in favour of  Generate buttons
placed directly below Career Summary, Voice & Personality, and each Mission
& Values row. Prompts now incorporate the live field value as a draft to
improve, plus resume experience bullets as context for Career Summary.
2026-02-26 13:40:52 -08:00
3cf729bb7a feat: searchable tag UI for skills/domains/keywords
Replace chip-button tag management with st.multiselect backed by bundled
suggestions. Existing user tags are preserved as custom options alongside
the suggestion list. Custom tag input validates through filter_tag() before
adding — rejects URLs, profanity, overlong strings, and bad characters.
Changes auto-save on multiselect interaction; custom tags append on + click.
2026-02-26 13:14:55 -08:00
93bf6b3c6f feat: bundled skills suggestion list and content filter utility
- config/skills_suggestions.yaml: 168 curated tags across skills (77),
  domains (40), keywords (51) covering CS/TAM/ops and common tech roles;
  structured for future community aggregate (paid tier backlog)
- scripts/skills_utils.py: filter_tag() rejects blanks, URLs, profanity,
  overlong strings, disallowed chars, and repeated-char runs;
  load_suggestions() reads bundled YAML per category
2026-02-26 13:09:32 -08:00
e982fa7a8b fix: resume CID glyphs, resume YAML path, PyJWT dep, candidate voice & mission UI
- resume_parser: add _clean_cid() to strip (cid:NNN) glyph refs from ATS PDFs;
  CIDs 127/149/183 become bullets, unknowns are stripped; applied to PDF/DOCX/ODT
- resume YAML: canonicalize plain_text_resume.yaml path to config/ across all
  references (Settings, Apply, Setup, company_research, migrate); was pointing at
  unmounted aihawk/data_folder/ in Docker
- requirements/environment: add PyJWT>=2.8 (was missing; broke Settings page)
- user_profile: add candidate_voice field
- generate_cover_letter: inject candidate_voice into SYSTEM_CONTEXT; add
  social_impact mission signal category (nonprofit, community, equity, etc.)
- Settings: add Voice & Personality textarea to Identity expander; add
  Mission & Values expander with editable fields for all 4 mission categories
- .gitignore: exclude CLAUDE.md, config/plain_text_resume.yaml,
  config/user.yaml.working
- search_profiles: add default profile
2026-02-26 12:32:28 -08:00
7ca20eec42 feat: ODT support, two-column PDF column-split extraction, title/company layout detection hardening 2026-02-26 10:33:28 -08:00
1775c7fa36 fix: harden resume section detection — anchor patterns to full line, expand header synonyms, fix name heuristic for hyphenated/middle-initial names, add parse diagnostics UI 2026-02-26 09:28:31 -08:00
26563a0990 refactor: replace LLM-based resume parser with section regex parser
Primary parse path is now fully deterministic — no LLM, no token limits,
no JSON generation. Handles two-column experience headers, institution-before-
or-after-degree education layouts, and header bleed prevention via
looks_like_header detection.

LLM path retained as optional career_summary enhancement only (1500 chars,
falls back silently). structure_resume() now returns tuple[dict, str].
Tests updated to match the new API.
2026-02-26 07:34:25 -08:00
c8d8434371 fix: resume parser — max_tokens, json-repair fallback, logging, PYTHONUNBUFFERED 2026-02-26 00:00:23 -08:00
af53f0a5eb fix: add python-docx to container requirements 2026-02-25 23:43:30 -08:00
70b385f3fd fix: add /v1 prefix to all license server API paths 2026-02-25 23:35:58 -08:00
6585d9ec75 feat: License tab in Settings (activate/deactivate UI) + startup refresh 2026-02-25 23:08:20 -08:00
fa1f36dc8d feat: wire license.effective_tier into tiers.py; add dev_override priority 2026-02-25 23:05:55 -08:00
7d5a706202 feat: license.py client — verify_local, effective_tier, activate, refresh, report_usage 2026-02-25 22:53:11 -08:00
4da5e0a2a4 fix: GPU detection + pdfplumber + pass GPU env vars into app container
- preflight.py now writes PEREGRINE_GPU_COUNT and PEREGRINE_GPU_NAMES to
  .env so the app container gets GPU info without needing nvidia-smi access
- compose.yml passes PEREGRINE_GPU_COUNT, PEREGRINE_GPU_NAMES, and
  RECOMMENDED_PROFILE as env vars to the app service
- 0_Setup.py _detect_gpus() reads PEREGRINE_GPU_NAMES env var first;
  falls back to nvidia-smi (bare / GPU-passthrough environments)
- 0_Setup.py _suggest_profile() reads RECOMMENDED_PROFILE env var first
- requirements.txt: add pdfplumber (needed for resume PDF parsing)
2026-02-25 21:58:28 -08:00
c7fe1626a7 fix: add app/__init__.py so wizard submodule is importable inside Docker
Without __init__.py, Python treats app/ as a namespace package that
doesn't resolve correctly when running from WORKDIR /app inside the
container. 'from app.wizard.step_hardware import ...' raises
ModuleNotFoundError: No module named 'app.wizard'; 'app' is not a package
2026-02-25 21:41:09 -08:00
1d228b293b fix: stub-port adoption — stubs bind free ports, app routes to external via host.docker.internal
Three inter-related fixes for the service adoption flow:
- preflight: stub_port field — adopted services get a free port for their
  no-op container (avoids binding conflict with external service on real port)
  while update_llm_yaml still uses the real external port for host.docker.internal URLs
- preflight: write_env now uses stub_port (not resolved) for adopted services
  so SEARXNG_PORT etc point to the stub's harmless port, not the occupied one
- preflight: stub containers use sleep infinity + CMD true healthcheck so
  depends_on: service_healthy is satisfied without holding any real port
- Makefile: finetune profile changed from [cpu,single-gpu,dual-gpu] to [finetune]
  so the pytorch/cuda base image is not built during make start
2026-02-25 21:38:23 -08:00
7c62935371 fix: ollama docker_owned=True; finetune gets own profile to avoid build on start
- preflight: ollama was incorrectly marked docker_owned=False — Docker does
  define an ollama service, so external detection now correctly disables it
  via compose.override.yml when host Ollama is already running
- compose.yml: finetune moves from [cpu,single-gpu,dual-gpu] profiles to
  [finetune] profile so it is never built during 'make start' (pytorch/cuda
  base is 3.7GB+ and unnecessary for the UI)
- compose.yml: remove depends_on ollama from finetune — it reaches Ollama
  via OLLAMA_URL env var which works whether Ollama is Docker or host
- Makefile: finetune target uses --profile finetune + compose.gpu.yml overlay
2026-02-25 21:24:33 -08:00
9c1f894446 feat: smart service adoption in preflight — use external services instead of conflicting
preflight.py now detects when a managed service (ollama, vllm, vision,
searxng) is already running on its configured port and adopts it rather
than reassigning or conflicting:

- Generates compose.override.yml disabling Docker containers for adopted
  services (profiles: [_external_] — a profile never passed via --profile)
- Rewrites config/llm.yaml base_url entries to host.docker.internal:<port>
  so the app container can reach host-side services through Docker's
  host-gateway mapping
- compose.yml: adds extra_hosts host.docker.internal:host-gateway to the
  app service (required on Linux; no-op on macOS Docker Desktop)
- .gitignore: excludes compose.override.yml (auto-generated, host-specific)

Only streamlit is non-adoptable and continues to reassign on conflict.
2026-02-25 19:23:02 -08:00
e3fbdd5502 docs: use ./manage.sh setup in quickstart 2026-02-25 17:18:03 -08:00
04915d33be docs: update README — manage.sh CLI reference + correct Forgejo clone URL 2026-02-25 16:59:34 -08:00
ca278d5b41 feat: add manage.sh — single CLI entry point for beta testers 2026-02-25 16:51:30 -08:00
775d54d605 fix: fix dual-gpu port conflict + move GPU config to overlay files
- Remove ollama-gpu service (was colliding with ollama on port 11434)
- Strip inline deploy.resources GPU blocks from vision and vllm
- Add compose.gpu.yml: Docker NVIDIA overlay for ollama (GPU 0),
  vision (GPU 0), vllm (GPU 1), finetune (GPU 0)
- Fix compose.podman-gpu.yml: rename ollama-gpu → ollama to match
  service name after removal of ollama-gpu
- Update Makefile: apply compose.gpu.yml for Docker + GPU profiles
  (was only applying podman-gpu.yml for Podman + GPU profiles)
2026-02-25 16:44:59 -08:00
bcde4c960e feat: wire fine-tune UI end-to-end + harden setup.sh
- setup.sh: replace docker-image-based NVIDIA test with nvidia-ctk validate
  (faster, no 100MB pull, no daemon required); add check_docker_running()
  to auto-start the Docker service on Linux or warn on macOS
- prepare_training_data.py: also scan training_data/uploads/*.{md,txt}
  so web-uploaded letters are included in training data
- task_runner.py: add prepare_training task type (calls build_records +
  write_jsonl inline; reports pair count in task result)
- Settings fine-tune tab: Step 1 accepts .md/.txt uploads; Step 2 Extract
  button submits prepare_training background task + shows status; Step 3
  shows make finetune command + live Ollama model status poller
2026-02-25 16:31:53 -08:00
740b0ea45a feat: containerize fine-tune pipeline (Dockerfile.finetune + make finetune)
- Dockerfile.finetune: PyTorch 2.3/CUDA 12.1 base + unsloth + training stack
- finetune_local.py: auto-register model via Ollama HTTP API after GGUF
  export; path-translate between finetune container mount and Ollama's view;
  update config/llm.yaml automatically; DOCS_DIR env override for Docker
- prepare_training_data.py: DOCS_DIR env override so make prepare-training
  works correctly inside the app container
- compose.yml: add finetune service (cpu/single-gpu/dual-gpu profiles);
  DOCS_DIR=/docs injected into app + finetune containers
- compose.podman-gpu.yml: CDI device override for finetune service
- Makefile: make prepare-training + make finetune targets
2026-02-25 16:22:48 -08:00
cfbe1cdf1a feat: prompt for model weights directory during install
Interactive prompt lets users with split-drive setups point Ollama and
vLLM model dirs at a dedicated storage drive. Reads current .env value
as default so re-runs are idempotent. Skips prompts in non-interactive
(piped) mode. Creates the target directory immediately and updates .env
in-place via portable awk (Linux + macOS). Also simplifies next-steps
output since model paths are now configured at install time.
2026-02-25 16:08:14 -08:00
57a05417dc fix: repair beta installer path for Docker-first deployment
- llm.yaml + example: replace localhost URLs with Docker service names
  (ollama:11434, vllm:8000, vision:8002); replace personal model names
  (alex-cover-writer, llama3.1:8b) with llama3.2:3b
- user.yaml.example: update service hosts to Docker names (ollama, vllm,
  searxng) and searxng port from 8888 (host-mapped) to 8080 (internal)
- wizard step 5: fix hardcoded localhost defaults — wizard runs inside
  Docker, so service name defaults are required for connection tests to pass
- scrapers/companyScraper.py: bundle scraper so Dockerfile COPY succeeds
- setup.sh: remove host Ollama install (conflicts with Docker Ollama on
  port 11434); Docker entrypoint handles model download automatically
- README + setup.sh banner: add Circuit Forge mission statement
2026-02-25 16:03:10 -08:00
4f67be4020 feat: add Ollama install + service start + model pull to setup.sh 2026-02-25 15:42:56 -08:00
7b53e6fd75 feat: Podman support — auto-detect COMPOSE, CDI GPU override, podman-compose in setup.sh 2026-02-25 15:36:36 -08:00
6be0566335 docs: fix license server paths — dev under CircuitForge/, live at /devl/ 2026-02-25 15:28:32 -08:00
1e6950893a docs: CircuitForge license server implementation plan (11 tasks) 2026-02-25 15:27:39 -08:00
b40dda3b91 docs: CircuitForge license server design doc
RS256 JWT, FastAPI + SQLite, multi-product schema, offline-capable
client integration. Covers server, Peregrine client, deployment,
admin workflow, and testing strategy.
2026-02-25 15:21:07 -08:00
8ceb1d2ebc docs: mark cover letter refinement complete in backlog + changelog 2026-02-25 14:44:50 -08:00
7fab2a0cd3 feat: cover letter iterative refinement — feedback UI + backend params
- generate() accepts previous_result + feedback; appends both to LLM prompt
- task_runner cover_letter handler parses params JSON, passes fields through
- Apply Workspace: "Refine with Feedback" expander with text area + Regenerate
  button; only shown when a draft exists; clears feedback after submitting
- 8 new tests (TestGenerateRefinement + TestTaskRunnerCoverLetterParams)
2026-02-25 14:44:20 -08:00
37ce9fb1f8 docs: finalise Circuit Forge product suite naming + product brief 2026-02-25 14:16:56 -08:00
76e97bd1cb docs: backlog — Circuit Forge product expansion (heinous tasks platform) 2026-02-25 14:02:07 -08:00
c1381c65ba docs: mark email sync test checklist complete 2026-02-25 13:56:55 -08:00
f3cfd258c6 test: complete email sync test coverage — 44 new tests across all checklist sections 2026-02-25 13:55:55 -08:00
3076f051d7 chore: mkdocs deps, CHANGELOG, remove dead Resume Editor page, backlog gap items 2026-02-25 13:51:13 -08:00
ddabf85a3d docs: LICENSE-MIT + LICENSE-BSL + updated README for 7-step wizard and current feature set 2026-02-25 12:06:28 -08:00
0ba27c3939 docs: mkdocs wiki — installation, user guide, developer guide, reference
Adds a full MkDocs documentation site under docs/ with Material theme.

Getting Started: installation walkthrough, 7-step first-run wizard guide,
Docker Compose profile reference with GPU memory guidance and preflight.py
description.

User Guide: job discovery (search profiles, custom boards, enrichment),
job review (sorting, match scores, batch actions), apply workspace (cover
letter gen, PDF export, mark applied), interviews (kanban stages, company
research auto-trigger, survey assistant), email sync (IMAP, Gmail App
Password, classification labels, stage auto-updates), integrations (all 13
drivers with tier requirements), settings (every tab documented).

Developer Guide: contributing (dev env setup, code style, branch naming, PR
checklist), architecture (ASCII layer diagram, design decisions), adding
scrapers (full scrape() interface, registration, search profile config,
test patterns), adding integrations (IntegrationBase full interface, auto-
discovery, tier gating, test patterns), testing (patterns, fixtures, what
not to test).

Reference: tier system (full FEATURES table, can_use/tier_label API, dev
override, adding gates), LLM router (backend types, complete() signature,
fallback chains, vision routing, __auto__ resolution, adding backends),
config files (every file with field-level docs and gitignore status).

Also adds CONTRIBUTING.md at repo root pointing to the docs site.
2026-02-25 12:05:49 -08:00