- _MISSION_SIGNALS: add health category (pharma, clinical, patient care, etc.)
listed last so music/animals/education/social_impact take priority
- _MISSION_DEFAULTS: health note steers toward people-first framing, not
industry enthusiasm — focuses on patients navigating rare/invisible journeys
- _trim_to_letter_end(): cuts output at first sign-off + first name to prevent
fine-tuned models from looping into repetitive garbage after completing letter
- generate(): pass max_tokens=1200 to router (prevents runaway output)
- user.yaml.example: add health + social_impact to mission_preferences,
add candidate_voice field for per-user voice/personality context
- Add _mixed_mode_vram_warning() to flag low VRAM on GPU 1 in mixed mode
- Wire download size report block into main() before closing border line
- Wire mixed-mode VRAM warning into report if triggered
- Write DUAL_GPU_MODE=ollama default to .env for new 2-GPU setups (no override if already set)
- Promote import os to top-level (was local import inside get_cpu_cores)
The package is never imported in the app — it was pulling torch + CUDA
(~7GB) into the main app container for no reason. AIHawk runs in its own
conda env (aihawk-env) outside Docker per design.
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.
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.
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.
- 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)
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).
- 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
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.
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.
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.
- 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)
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
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
- 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
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.
- 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)
- 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