# OpenCode Master Prompt — "Does It Sound Broken?" Paste the block below into OpenCode (or Codex/Cursor) from inside the `sound-broken/` folder. The project is **already scaffolded** — your job is to verify it, fill the remaining gaps, get it running, and deploy. A from-scratch fallback is included at the end in case you start in an empty folder. --- ## PROMPT TO PASTE > You are finishing a Hugging Face Gradio hackathon project in the current > folder. The architecture is already implemented across these files: > `app.py`, `audio_analyzer.py`, `fault_rules.py`, `feature_prompt.py`, > `json_guard.py`, `requirements.txt`, `README.md`, `assets/custom.css`, > `assets/generate_samples.py`, `tests/test_pipeline.py`. > > **Concept (do not change it):** audio → deterministic librosa features (CPU) > → transparent rule engine ranks candidate faults (CPU) → Nemotron-3-Nano-4B > picks + explains the best-supported one (GPU) → validated JSON → UI. The model > NEVER hears raw audio; it only reasons over measured features and rule-derived > candidates. The rule layer is the floor — `json_guard.py` must snap any > ungrounded model output back to the top deterministic candidate. > > **Hard constraints (keep these):** > - Model id: `nvidia/NVIDIA-Nemotron-3-Nano-4B-BF16` (or `-FP8`). NEVER use > `nvidia/Nemotron-3-Nano-4B-Instruct` — it 404s. > - **Architecture: Modal-only compute.** The HF Space (`app.py`) is a THIN > Gradio client that depends on only `gradio` + `modal`. ALL heavy work > (librosa feature extraction + rule ranking + the 4B model) runs inside the > Modal container defined in `modal_backend.py` (`@app.cls(gpu="A10G")` with > `@modal.enter()` to load the model and a `@modal.method()` pipeline). Do NOT > put librosa/torch/transformers in the Space's requirements.txt or import them > in app.py. Do NOT use HF ZeroGPU/`spaces.GPU`. > - The Space looks the backend up with `modal.Cls.from_name("sound-broken", > "Diagnoser")` and calls `.run.remote(audio_bytes, suffix, appliance)`, which > returns a JSON-serializable dict `{ok, error, features, candidates, result}`. > - Appliance type is a REQUIRED input. Greedy decoding (`do_sample=False`), > `max_new_tokens=384`, use `tokenizer.apply_chat_template`. > - Robustness is non-negotiable: every handler returns a friendly result and > never raises; all model-derived text is `html.escape`d before rendering. > > **Do these tasks in order, and report (don't guess) on any blocker:** > 1. `pip install -r requirements.txt`. > 2. `python assets/generate_samples.py` to create the 4 test WAVs. > 3. `python -m pytest tests/ -q` — all tests must pass. The bearing sample MUST > trigger a bearing candidate; the good sample MUST stay calm; empty audio MUST > NOT crash. Fix `audio_analyzer.py` / `fault_rules.py` if any fail. > 4. `SOUNDBROKEN_MOCK=1 python app.py` and confirm the UI loads, both tabs work, > Examples render an urgency banner + evidence panel, and Compare shows a > before/after delta. Fix any Gradio wiring issues. > 5. Review the CSS renders the industrial amber-on-charcoal theme; tighten if > the verdict card or urgency colors look off. Verify mobile (single column). > 6. If a GPU is available, unset MOCK and confirm a real diagnosis returns valid > grounded JSON. If the model OOMs, switch `MODEL_ID` to the `-FP8` variant. > 7. Verify `README.md` frontmatter (sdk gradio, hardware zero-gpu, correct model > tag). Add real screenshots once the UI runs. > 8. Expand `fault_rules.RULES` to cover the remaining appliances in > `app.APPLIANCES` (Tumble dryer, Refrigerator/Freezer, Air conditioner, > Vacuum cleaner, Dishwasher, Microwave, Bicycle, Power drill). 2–4 rules each, > same `Rule(name, urgency, weight, when, evidence)` shape, weights 0.6–0.9, > evidence templates that reference real feature fields. Keep `when` lambdas > defensive (no exceptions on edge values). > > **Definition of done:** tests green; `python app.py` runs end-to-end; all 4 > examples produce grounded reproducible diagnoses with a visible evidence chain; > Compare tab shows a numeric delta; no unhandled exception on empty/garbage audio; > README renders on a Space. Work incrementally and run the tests after each change. > > **Stretch (only if time remains):** add `finetune/train.py` — a LoRA fine-tune > of the 4B model on ~200–300 (feature-description → known-fault) pairs derived > from the MIMII dataset; document uploading the adapter to the Hub for the > Well-Tuned badge. Do not let this block the core submission. --- ## FROM-SCRATCH FALLBACK (only if the folder is empty) If the scaffold is missing, build it module by module in this exact order, running a quick check after each: (1) `audio_analyzer.py` with the `AudioFeatures` dataclass + NaN-guarded `extract_features`; (2) `fault_rules.py` with `Rule`, `Candidate`, `RULES` tables and `rank_candidates` (always returns ≥1 candidate); (3) `feature_prompt.py` `build_diagnosis_prompt(features, candidates, appliance)` demanding strict JSON; (4) `json_guard.py` `validate()` with rule fallback; (5) `app.py` Gradio Blocks with `@spaces.GPU`, mock mode via `SOUNDBROKEN_MOCK`, Diagnose + Compare tabs, evidence accordion; (6) `assets/generate_samples.py`, `assets/custom.css`, `tests/`, `requirements.txt`, `README.md` with the frontmatter above. Use the constraints listed in the main prompt verbatim.