Spaces:
Sleeping
Sleeping
Commit History
-
[assess] Remove web search entirely (prompt, code, module, test, env)
Hélder Monteiro +1: CodexThe model was narrating web searches and 'current information' it could not actually do, because the assessment PROMPT still told it to use web_search even though the tool was unwired (not in ASSESSMENT_TOOLS). That both misled the user ('feels like web search is enabled') and risked fabricated 'current' claims. - Prompt: drop all web_search references; state plainly there is no web access and to never claim current/latest info it cannot retrieve. - assessment.py: remove the dead web_search status chip and the now-moot outbound-query privacy guard; update the docstring. - Delete the dormant agent/tools/web_search.py module (imported nowhere active). - Tests: drop test_web_search_real and the Tavily gating (assessment uses only local tools now). - .env.example: remove the Tavily key + stale per-phase model vars; note there is no web search. Co-authored-by: Codex <noreply@openai.com>79d3fac -
[fix] Choice controls never toggle visibility; non-signatories not asylum dests
Hélder Monteiro +1: Codex1) The recurring 'press Continue to show options' bug. Real root cause: toggling a gr.CheckboxGroup from hidden->visible does NOT build its option DOM, so it paints empty until the next interaction — no in-generator/round-trip trick fixed it. Permanent fix: mount the choice controls (radio + both checkbox groups) VISIBLE and drive them by their CHOICES alone (empty = collapsed via a CSS :has rule). Setting choices on an already-mounted-visible group always renders (the one behaviour we'd confirmed works). country/text still toggle visible (those components handle it fine). This also kills the 'all controls visible / stale English labels' leak. 2) Pakistan (a non-signatory with no UNHCR) was shown as an asylum destination with a UNHCR/RSD roadmap. Protection-case recommendations now require the country to be a Convention signatory; non-signatories are dropped. And the roadmap's first step adapts: 'Register with UNHCR' only where UNHCR runs registrati…d22000a -
[assess] Honest handling of economic (non-protection) cases
Hélder Monteiro +1: CodexEconomic migration has no right to asylum under the 1951/1969 Conventions, yet the app showed 'Strong match' asylum cards and a UNHCR/RSD roadmap to everyone regardless of case_type — fabricated legal guidance for an economic migrant (CLAUDE.md: wrong output is worse than no output). - Prompt: explicit rule that economic hardship ('no jobs', 'better life') is NOT a protection ground — classify as economic_or_other and point to regular work/study routes, not asylum. - country_lookup: expose non-signatory economic fields (work visa, job market, kafala, honest strategic_guidance caveats) + a curated work_route_countries() shortlist (Gulf labour markets with employer-sponsored work visas — the historically accessible routes, unlike strict Western/EU criteria). - assessment: for economic_or_other, use the deterministic labour shortlist — never the small model's possibly-Western asylum picks. - recommendations: render economic cases as honest 'Work route' cards (work visa, job…180ae9b -
[ux] Show multi-select options instantly (no extra Continue)
Hélder Monteiro +1: CodexThe single shared CheckboxGroup swapped its choices at reveal time, which Gradio renders a beat late — so the persecution-grounds / documents options only appeared after an extra Continue press. Give each multi-select question its own pre-mounted group whose (language-correct) choices are set once and never swapped; only visibility toggles thereafter, so options paint at once. Co-authored-by: Codex <noreply@openai.com>597cc8f
-
[agentic] Port pi loop hooks + LLM-drafted editable (Word) documents
Hélder Monteiro +1: CodexAudited /tmp/pi and ported its agentic control architecture into Refuge's Python loop, then used it to make the assessment and documents genuinely agentic (the hackathon point: small-LLM agentic AI). Agent framework (agent/loop.py) — Python port of pi's AgentLoopConfig hooks: - LoopHooks: transform_context, before_tool_call, after_tool_call, should_stop_after_turn, prepare_next_turn; plus tool `terminate` handling. Assessment now uses the hooks: - should_stop_after_turn ends the run once the @@ASSESSMENT block is produced (no rambling); before_tool_call blocks web_search queries containing the person's private narrative (privacy, ARCHITECTURE §Security). Documents are now agentic + editable: - agent/drafting.py: the LLM drafts an in-depth, first-person personal statement from the person's own answers, in their language, with [placeholders] to complete (deterministic fallback if the model is down; nothing fabricated). - doc_generator: exports every document as editable Word…b93c45d -
[fix] Fully-scripted multilingual interview (no LLM) + remove walkthrough chrome
Hélder Monteiro +1: CodexPer testing feedback: letting the LLM phrase interview questions caused wrong questions, mismatched controls (Yes/No on a free-text question), repeats, and drift. Replaced it with a deterministic, fully-scripted interview. - app/interview_script.py: fixed question bank, each with a fixed control, pre-translated into all 10 languages, templated with collected values (e.g. "what happened in {origin}"). No model is used in the interview at all. - app/phases/interview.py rewritten: pure lookup/render; controls are correct by construction; one question at a time; guaranteed progression to Review; on confirm it advances state -> ASSESSMENT (language-independent trigger). - reason-for-leaving is now a free-text narrative (templated with origin), not reductive pills, per feedback. - removed the meta "Phase N — …" walkthrough descriptions from every screen (they were design-walkthrough scaffolding, not product UI). - app.py: assessment trigger keys off state==ASSESSMENT (was a frag…e6d3ad1 -
[fix] Deterministic slot-filling interview (agentic flow, consistent UI)
Hélder Monteiro +1: CodexThe interview previously depended on the small model to emit a @@RESPONDER directive and drive phase progression — which it did inconsistently (controls flip-flopped, intro varied, questions repeated, phases never advanced so the flow never proceeded to assessment). Re-architected the pi way: the APP deterministically drives the loop, the LLM only phrases. - app/phases/interview.py: a fixed, ordered SLOTS plan; each slot has a fixed control (country picker / choice pills / text) and target session.interview field. The app shows the right control every time, advances one step per turn, drives the phase rail, and always reaches Review -> Assessment. The LLM only phrases each question warmly in the chosen language and acknowledges the prior answer (thinking off). Answers are captured straight into session.interview (real data for the assessment facts + documents). - removed the brittle directive parsing from the interview path. - tests updated to the deterministic contract; r…aa796c4 -
[T049-T055 + UX] Phase 5 documents + single-model + responder/UX fixes
Hélder Monteiro +1: CodexPhase 5 — Document package: - agent/tools/doc_generator.py + 4 WeasyPrint templates: real PDFs from session data, amber-highlighted pre-fills, blanks (never [NAME]/PLACEHOLDER), logged field sources; zip for "Download all"; head-less preview snippet - app/phases/documents.py: preview + evidence checklist (pre-checked from documents_available) + file list + Download all + Start over - nav: Recommendations "Prepare my documents" -> Documents; Start over -> intake - launch(allowed_paths=[tempdir]) so Gradio can serve the generated PDFs - tests: 8 document tests (real PDF text via pypdf 6.12.2, pinned one-before) Single LLM + UX fixes (from live testing): - one model end-to-end: MODEL_ID=lfm2.5:8b (fast ~2s, tool-calling + good multilingual); removed per-phase model split (no fallback, hackathon rule) - languages limited to those lfm2.5:8b handles well (probe-verified): English, French, Spanish, Portuguese, Arabic, Hindi, Chinese, Japanese, Korean, Russian - responder: free-text…f05e15f -
[T044-T048 + data] Phase 4 recommendations + real UNHCR stats integration
Hélder Monteiro +1: CodexPhase 4 — Recommendations + roadmap: - app/phases/recommendations.py: 2-3 country cards (flag, Fraunces name, match badge from real fields, real facts block, prep details, select button), auto- select top country, vertical roadmap (>=5 steps, country-adapted, contact/time chips, header names country). Cards/facts come from country_lookup data. - app/app.py: assessment -> recommendations handoff via .then() - tests/integration/test_recommendations.py (offline, real country data) Data layer — downloaded, integrated, tested (curated stays authoritative): - country_lookup: curated specs/data/countries.json is ALWAYS the structural base (orgs, signatories, asylum systems); countries_enriched.json overlays ONLY numeric stats.* (never replaces curated fields). Added resolve_iso3. - fix enrich_downloader: ISO3 is "iso" not "iso3" (was enriching 0/152 -> 151); complementary protection is "dec_other" not "dec_complementary" - fix query_data: filter on coo_iso/coa_iso (was coo_code/c…7a05b1b -
[T035-T043] Phase 3 — situation assessment (reasoning stream + real tools)
Hélder Monteiro +1: Codex- agent/tools/country_lookup.py: offline lookup from countries.json (enriched if present), flat schema (unhcrPresence, processingTimeMonths, acceptanceRate, primaryLanguage, requiredDocuments, legalAidOrgs, unhcrOffice, tier, warning); not_found instead of fabrication; PENDING stats surfaced as None (T036/SC-026) - agent/tools/web_search.py: real Tavily search via httpx; fails loudly w/o key or on API error (no fake results) (T035/SC-025) - app/prompts/assessment.md: 5-step scaffold (1951 + AU 1969 grounds, transit safety, find programmes, rank 2-3) + @@ASSESSMENT structured block (T038) - app/assessment_parse.py: parse grounds/risk/countries from the block - app/phases/assessment.py: facts sidebar (8 fields), live reasoning stream, progress bar, "Searching: …" tool chips; stream_assessment core runs the model with both tools, then attaches authoritative country_lookup data to ranked recommendations (origin excluded) into session.assessment (T037/T039/T040) - app/app.py…4270181 -
[T017-T029] Phase 1 — agent loop + interview core
Hélder Monteiro +1: Codex- agent/loop.py: full turn cycle (already streamed); separate system prompt from persisted history (no accumulation); create_loop() session factory (T019) - app/prompts/interview.md: 4 sub-phase question bank + @@RESPONDER directive (T020) - app/prompt_loader.py: compose system + interview prompts (T021) - app/responder.py: parse @@RESPONDER -> ResponderSpec, lenient fallback - app/phases/interview.py: mockup-faithful progress rail, chat bubbles, thinking indicator, structured responder (choice/country/text), ghost "Save and continue later"; real per-delta streaming; turn_end sets responder mode; agent_end advances state (T022-T025) - app/countries.py: country selector choices from countries.json - app/design_tokens.py: align CSS var names to mockup (--primary/--bg/--r-md/ --s-md) + shadows/maxw from DESIGN §4/§5; app.py hero updated - app/app.py: mount interview, auto-start first question via demo.load Tests (33 pass): responder parse, event contracts (T028), loop isolation…e16f16c -
[T001-T016] Phase 0 — project setup: agent loop, state machine, Gradio skeleton
Hélder Monteiro +1: Codex- requirements.txt + pyproject.toml pinned one release before latest (gradio 6.15.2, weasyprint 68.1, httpx 0.28.0, ollama 0.6.1, litellm 1.87.1, pytest 9.0.2, pytest-asyncio 1.3.0) - agent/events.py: 8 typed AgentEvent dataclasses - agent/loop.py: pure-Python async AgentLoop (stream, tools, steer, abort, error-as-event); agent/tools/base.py AgentTool contract - app/state/session.py: forward-only interview state machine - app/app.py + app/design_tokens.py: Gradio skeleton, DESIGN.md :root tokens - app/prompts/system.md: Refuge case-worker persona - scripts/validate_design_tokens.py: T010 token validator - tests/unit: state machine (7) + loop ping (1) — all green Co-authored-by: Codex <noreply@openai.com>944f1ac