Resolve conflicts from main's Wave 0 (PR #1) landing after this branch was cut:
- useViewResource.ts: main's e352aae already fixes the render loop the same way
(load in a ref, dropped from deps) — took main's canonical version. My
independent fix is superseded (my branch predated e352aae, which is why the
loop reproduced live).
- JobApplicationsController.cs: keep BOTH main's IJobCvMatchService and my
AnalyticsService (ctor gets both optional params). GetAnalyticsOverview stays
delegated to AnalyticsService.
- Fold main's H3 additions into the extracted AnalyticsService: pipeline-driven
funnel (JobPipeline.Normalize/Stages) + time-in-stage (StageAnalytics) and add
StageDurationDto + TimeInStage to Models/AnalyticsDtos.cs, preserving the API
contract the frontend expects.
Build clean; backend suite 135/135 green.
The structured /cv/* calls funnel through a provider router so production can
offload a weak local GPU (GTX 1060) to a cloud provider without any .NET change.
Default stays "ollama" (keyless/local) and /summarize remains local distilbart.
- AI_PROVIDER=ollama|gemini|groq dispatch inside _ollama_generate_json/_text
(entry-point names kept, so no call sites change; Ollama path is byte-identical).
- Gemini (x-goog-api-key header, not URL query) and Groq (OpenAI-compatible
chat/completions) added via stdlib urllib — zero new dependencies.
- /health reports ai_provider + ai_provider_configured.
- Keys read from env only; never logged/committed.
- Compose + .env.example pass AI_PROVIDER/GEMINI_*/GROQ_* through.
Tests: 11 passed (default Ollama unchanged, Gemini/Groq dispatch, missing-key 503,
health reports provider).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The compose file shipped its own ollama service, so 'docker compose pull'
during deploy re-downloaded the Ollama image and a deploy that starts the
AI stack would spin up a second Ollama alongside an existing/shared one.
- ollama service moved behind a 'bundled-ollama' compose profile, so it is
excluded from the default pull/up (no duplicate, no re-download)
- ai-service no longer depends_on ollama and is documented to point at a
shared instance via OLLAMA_BASE_URL (e.g. http://<host>:11435)
- deploy.sh no longer names ollama in 'compose up'
To run a self-contained Ollama: docker compose --profile bundled-ollama up
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CRA's build runs fork-ts-checker in a forked process whose IPC needs
more than Docker's default 64MB /dev/shm; too little segfaults
'npm run build' (RpcIpcMessagePortClosedError / SIGSEGV) with no compile
error. Set shm_size on the frontend image build so production deploys
don't hit this. (CI runners need the same via their container options.)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>