riprap-nyc / OPEN-ISSUES.md
seriffic's picture
ship: v0.5.0 code changes β€” compare UI + cleanup pass
caa28aa

Open Issues β€” post-hackathon triage

These bugs were identified in the audit/AUDIT-2026-05-06.md pass. All are in experiments/ (exploratory/reproduction code) and were explicitly left untouched pre-demo per Adam's instruction.


1. experiments/17 β€” F821 numpy annotation race

File: experiments/17_riprap_integration/terramind_nyc.py:117 Ruff code: F821 (3Γ—) Issue: Type annotation references np (numpy) before it is imported at module top. Currently masked by from __future__ import annotations (lazy eval). Will fail if Python ever evaluates it eagerly, or if this module is ported to a context that drops the future import. Fix: Move import numpy as np to module top.


2. experiments/18 β€” f-string syntax only valid on Py 3.12+

File: experiments/18_terramind_nyc_lora/shared/eval_adapter.py:125 Ruff code: invalid-syntax Issue: Inner f-string reuses outer quote style (valid in Py 3.12, syntax error in Py 3.10). The HF Space (Py 3.10) cannot import this file. Currently local-only; will error if anyone tries to ship it. Fix: Change inner f-string quotes or use .format().


3. experiments/05 β€” closure captures loop variable

File: experiments/05_terramind_nyc_finetune/training/verify_phase1.py:438 Ruff code: B023 (2Γ—) Issue: Closure inside a for loop binds the loop variable by reference (all closures see the last value). The classic Python late-binding trap. May or may not be a bug depending on intent β€” needs a human eye on what the closure does. Fix: Rebind with a default arg: lambda x=x: ....


4. experiments/18 β€” possibly dead api assignment

File: experiments/18_terramind_nyc_lora/shared/publish_hf.py:107 Ruff code: F841 Issue: api is assigned (likely from HfApi()) but never used in the file. May be a bug (intended to call api.upload_file(...)) or a leftover from an edit. Needs a human eye. Fix: Either use api in the upload calls, or remove the assignment.


5. _merge_mellea puts requirements in both passed and failed

File: web/main.py:563 Issue: Uses set(a_passed + b_passed) (union) for requirements_passed. If leg A fails citations_resolve but leg B passes it, citations_resolve ends up in both requirements_passed and requirements_failed in the merged Mellea dict. The UI then shows "4/4 passed" with a contradictory "failed: citations_resolve" entry. Fix: Use intersection for requirements_passed:

"requirements_passed": list(set(_lst(a, "requirements_passed")) & set(_lst(b, "requirements_passed"))),

6. mellea.attempts wrong field name in persistSnapshot

File: web/sveltekit/src/routes/q/[queryId]/+page.svelte:598 Issue: finalResult?.mellea?.attempts is always undefined β€” the Mellea field is n_attempts. Falls back silently to the streaming attempt counter. The PDF/print snapshot always has wrong attempt metadata. Fix:

attempts: finalResult?.mellea?.n_attempts ?? attempt

7. NTA-typed compare targets fall through to single_address

File: web/main.py:514 Issue: addr_targets = [t for t in p.targets if t.get("type") == "address"] filters out NTA targets. When the planner returns type: "nta" for both sides of a compare query (e.g. "Compare Two Bridges to Battery Park City"), addr_targets is empty, the fallback runs the full raw query text through single_address, the geocoder finds no valid address, and the response is "No grounded data available." Fix: Accept "nta" targets and route each through the neighborhood intent instead of single_address, or accept both type values and pick the right intent per target.


8. iter_steps returns without final when FSM fails pre-iteration

File: app/fsm.py:1292–1294 Issue: If app.iterate() raises before any action completes (so final_state_holder["state"] is never set), iter_steps does a bare return after the error event. No final event is yielded. The SSE stream closes with an open Stone in the trace UI (the stone_done for the active Stone never fires), leaving the frontend in a non-terminal render state. Fix: Yield a synthetic final with an error flag when state is None:

if state is None:
    yield {"kind": "final", "paragraph": "", "error": "FSM failed before any action completed"}
    return