HearthNet / docs /reports /IMPROVEMENTS.md
GitHub Actions
feat: P0/P1 β€” Image, OCR, Translation tabs + styled headers on all tabs
b132c6e
|
Raw
History Blame Contribute Delete
11.5 kB

A newer version of the Gradio SDK is available: 6.20.0

Upgrade

HearthNet β€” Master Task & Improvement List

Updated June 15, 2026 Β· Priority order: highest impact first


βœ… DONE β€” Hackathon Critical

# Task Commit
C1 Demo video recorded and linked in README ee40c33
C2 Social post on X @zX14_7 ee40c33
C3 NVIDIA_API_KEY set in HF Space secrets β€”
C4 Deploy app_nemotron.py as second HF Space (HearthNet-Nemotron) feat/nemotron-space
C5 MiniCPM3-4B as default model in main Space (OpenBMB + Tiny Titan) ee40c33
C6 Modal deploy fix β€” scaledown_window replacing deprecated param ee40c33
C7 GitHub Codex commits pushed ee40c33
C8 NVIDIA API key removed from Gradio frontend (SEC-1 critical fix) 1c211eb
C9 /data permission graceful fallback β€” Space no longer crashes c9bf597

βœ… DONE β€” Services Wired Up

Previously implemented in code but never connected or visible:

# Task What was broken Commit
W1 Nemotron tab added to main Gradio UI nemotron.py existed, never imported c021486
W2 Voice tab (STT + TTS) β€” new voice.py STT/TTS services registered but no UI c021486
W3 FederationService (M14) registered in install_services() Never registered anywhere c021486
W4 ImageGenerateService gets Florence2Backend at init Was instantiated with empty backends=[] c021486
W5 edge-tts, faster-whisper, pytesseract added to requirements Not in requirements, so backends silently failed c021486
W6 HearthNet theme applied to main app (purple/dark) hearthnet_theme defined but never passed to gr.Blocks latest
W7 Custom CSS header, badges, animated status dot, button hover Main app had zero custom styling latest
W8 Voice tab asyncio pattern fixed for Gradio async context get_event_loop() fails inside Gradio's running loop latest

πŸ”΄ P0 β€” Must fix before next demo

P0-1 β€” Image tab: upload β†’ Florence2 describe

Impact: Shows off Florence2 + vision capability β€” judge can upload a photo and see AI describe it Effort: 1 hour File to create: hearthnet/ui/tabs/image.py Capability: img.describe@1.0 Add to ui/app.py: from hearthnet.ui.tabs.image import build_image_tab + with gr.Tab("πŸ–Ό Image"): build_image_tab(bus)

# Minimal implementation:
def build_image_tab(bus):
    img_input = gr.Image(type="filepath", label="Upload image")
    describe_btn = gr.Button("πŸ” Describe with Florence2", variant="primary")
    description_out = gr.Textbox(label="Description", lines=4)

    def _describe(path):
        import base64
        with open(path, "rb") as f:
            b64 = base64.b64encode(f.read()).decode()
        result = _run(bus.call("img.describe", (1,0), {"input": {"image_b64": b64}}))
        return result.get("output", {}).get("caption", result.get("caption", str(result)))

    describe_btn.click(_describe, inputs=[img_input], outputs=[description_out])

P0-2 β€” OCR tab: upload scan/PDF β†’ text

Impact: Tesseract/TrOCR β€” a common real-world need Effort: 45 min File to create: hearthnet/ui/tabs/ocr.py Capability: ocr.image@1.0, ocr.pdf@1.0

def build_ocr_tab(bus):
    ocr_input = gr.File(label="Upload image or PDF", file_types=[".png",".jpg",".pdf"])
    ocr_btn = gr.Button("πŸ“„ Extract Text", variant="primary")
    ocr_out = gr.Textbox(label="Extracted text", lines=10)

    def _ocr(file_path):
        cap = "ocr.pdf" if file_path.endswith(".pdf") else "ocr.image"
        import base64
        with open(file_path, "rb") as f:
            b64 = base64.b64encode(f.read()).decode()
        result = _run(bus.call(cap, (1,0), {"input": {"file_b64": b64}}))
        return result.get("output", {}).get("text", str(result))

    ocr_btn.click(_ocr, inputs=[ocr_input], outputs=[ocr_out])

P0-3 β€” Translation tab: text + language β†’ translated text

Impact: NLLB-200 covers 200 languages β€” real differentiator Effort: 30 min File to create: hearthnet/ui/tabs/translation.py Capability: trans.text@1.0

def build_translation_tab(bus):
    src_text = gr.Textbox(label="Text to translate", lines=5)
    src_lang = gr.Textbox(label="Source language", value="en")
    tgt_lang = gr.Textbox(label="Target language", value="de")
    translate_btn = gr.Button("🌍 Translate", variant="primary")
    out_text = gr.Textbox(label="Translation", lines=5)

    def _translate(text, src, tgt):
        result = _run(bus.call("trans.text", (1,0),
            {"params": {"source_lang": src, "target_lang": tgt},
             "input": {"text": text}}))
        return result.get("output", {}).get("text", str(result))

    translate_btn.click(_translate, inputs=[src_text, src_lang, tgt_lang], outputs=[out_text])

🟠 P1 β€” High value, medium effort

P1-1 β€” Apply styled HTML headers to ALL tabs

Current state: Only voice.py and nemotron.py have styled section headers. Ask, Chat, Mesh, etc. have plain Markdown. Fix: Add a gr.HTML(...) styled section header at the top of each build_*_tab() function, matching the gradient style in voice.py.

P1-2 β€” Rate limiting on /bus/v1/call and /relay/v1/*

File: app.py β€” _mount_bus_endpoints() Fix: Wire RateLimiter from hearthnet/bus/backpressure.py

from hearthnet.bus.backpressure import RateLimiter
_limiter = RateLimiter(max_calls=60, window_seconds=60)
@app.middleware("http")
async def _rate_limit(request, call_next):
    ip = request.client.host if request.client else "unknown"
    if request.url.path.startswith(("/bus/v1", "/relay/v1")):
        if not _limiter.allow(ip):
            return JSONResponse({"error": "rate_limited"}, status_code=429)
    return await call_next(request)

P1-3 β€” Capability token expiry enforcement

File: hearthnet/bus/router.py Fix: Check token.exp < time.time() before routing β€” exp is stored in the token but never validated.

P1-4 β€” E2E encryption as default in chat (M23)

File: hearthnet/services/chat/service.py Status: X3DH + Double Ratchet implemented in hearthnet/crypto/ but ChatService.send() sends plaintext Fix: Thread ratchet state through ChatService._sessions dict, encrypt payload before bus dispatch.

P1-5 β€” Wire node.start() properly in app.py

File: app.py Currently: node.install_services() called manually β€” skips mDNS, transport start, gossip sync Fix:

# Replace:
_node.install_services(corpus="community")
# With (in a thread or via asyncio.get_event_loop):
loop.run_until_complete(_node.start(corpus="community"))

P1-6 β€” Gossip sync between nodes (X02)

File: hearthnet/node.py β€” add to node.start() after step 9 Fix:

from hearthnet.events.sync import SyncServer
self._sync_server = SyncServer(self._event_log, self.peers)
asyncio.create_task(self._sync_server.run())

Enables marketplace posts and RAG documents to auto-replicate across mesh nodes.


🟑 P2 β€” Medium value

P2-1 β€” Evidence UI tab (M30)

Capabilities: evidence.claim.add, evidence.claim.attest, evidence.claim.dispute Service: EvidenceService β€” registered in research mode (install_extended_services(research=True)) File to create: hearthnet/ui/tabs/evidence.py Add to ui/app.py once implemented.

P2-2 β€” Civil Defense UI tab (M31)

Capabilities: civdef.alert.issue, civdef.cert.*, civdef.audit.chain Service: CivilDefenseService β€” registered in research mode File to create: hearthnet/ui/tabs/civdef.py

P2-3 β€” Routing trace as flow chart (U2)

Current state: Routing trace shown as plain text in Ask tab Fix: Render as HTML/Mermaid flow diagram showing scored candidates and winner.

P2-4 β€” Peer capability matrix in Mesh tab (U5)

File: hearthnet/ui/tabs/mesh.py Add: Table showing each discovered peer and their capabilities.

P2-5 β€” Dark mode toggle

File: hearthnet/ui/app.py Note: hearthnet/ui/theme.py already has emergency_theme as a dark variant. Add a toggle.

P2-6 β€” Model selection UI in Settings tab

Current state: Model is fixed at startup via MODEL_ID env var Fix: Add a dropdown in Settings showing available registered backends + restart hint.

P2-7 β€” Relay hub rate limiting

File: hearthnet/transport/relay_hub.py Fix: Max 5 join attempts per IP per minute to prevent roster flooding.


🟒 P3 β€” Future / research

P3-1 β€” ShardServer.forward() for distributed inference (M26)

File: hearthnet/distributed_inference/shard.py:75 β€” NotImplementedError Requires: torch model slicing, attention head partitioning across nodes

P3-2 β€” FedLearnCoordinator.aggregate() (M28)

File: hearthnet/fedlearn/coordinator.py:95 β€” NotImplementedError Requires: peft, LoRA delta accumulation, secure aggregation protocol

P3-3 β€” LoRa hardware serial port (M29)

File: hearthnet/lora/service.py:96 β€” silent stub without pyserial Fix: serial.Serial("/dev/ttyUSB0", 9600) + add pyserial>=3.5 to requirements

P3-4 β€” Browser ↔ Python mesh bridge

Files: webagent/src/mesh/browsermesh.js (PeerJS/WebRTC) Status: Browser mesh and Python relay run as separate isolated meshes Fix: Bidirectional WebRTC↔mailbox translation, ICE/TURN server

P3-5 β€” RelayDiscovery.start() (Phase 2 peer discovery)

File: hearthnet/discovery/relay.py:8 β€” NotImplementedError Fix: Poll /relay/v1/roster on a timer, add discovered peers to PeerRegistry

P3-6 β€” Publish to PyPI

Command: python -m build && twine upload dist/* Note: pyproject.toml is ready

P3-7 β€” Docker image publish

File: Dockerfile.slim exists Command: docker build -t hearthnet:latest . && docker push ghcr.io/ckal/hearthnet:latest


πŸ“‹ All Tasks β€” Status at a Glance

Priority Task Status
C1–C9 Hackathon critical items βœ… All done
W1–W8 Service/UI wiring βœ… All done
P0-1 πŸ–Ό Image describe tab βœ… Done
P0-2 πŸ“„ OCR tab βœ… Done
P0-3 🌍 Translation tab βœ… Done
P1-1 Styled headers on all tabs βœ… Done
P1-2 Rate limiting on bus/relay ⏳ Open
P1-3 Token expiry enforcement ⏳ Open
P1-4 E2E encryption default ⏳ Open
P1-5 node.start() wiring ⏳ Open
P1-6 Gossip sync ⏳ Open
P2-1 Evidence UI tab ⏳ Open
P2-2 CivilDefense UI tab ⏳ Open
P2-3 Routing trace flow chart ⏳ Open
P2-4 Peer capability matrix ⏳ Open
P2-5 Dark mode toggle ⏳ Open
P2-6 Model selection UI ⏳ Open
P2-7 Relay hub rate limiting ⏳ Open
P3-1 M26 distributed inference ⏳ Future
P3-2 M28 federated learning ⏳ Future
P3-3 M29 LoRa hardware ⏳ Future
P3-4 Browser↔Python mesh bridge ⏳ Future
P3-5 RelayDiscovery.start() ⏳ Future
P3-6 PyPI publish ⏳ Future
P3-7 Docker image publish ⏳ Future

See Also