# 🐛 Bugs

Tracked bugs with stable IDs. Once assigned, an ID never changes or gets reused.

| Status | Meaning |
|--------|---------|
| `open` | Not yet planned |
| `planned` | Pulled into an active feature |
| `shipped` | Fixed and deployed |
| `wont-fix` | Intentionally declined |

---

### B-001 — Toast notification z-order and auto-dismiss on small terminals
**Status:** open
**Area:** TUI / ToastWidget

On small terminals (e.g., 21 rows), toast notifications like "on the case" don't auto-dismiss cleanly and can get buried behind content. If the user returns to the input immediately, the toast lingers behind the commands/main screen and takes longer to dismiss.

**Expected:** Returning to input should immediately dismiss the toast.

---

### B-003 — Quit confirmation modal not showing consistently; text truncated
**Status:** open
**Area:** TUI / Quit flow

Multiple issues with the quit confirmation modal:
- Modal only appears when there's an active lead, but should appear every time the user quits (distinction isn't obvious)
- Modal text is cut off: "You have an active lead. Quit anyway? Your progress is"
- Quitting via "q", "quit", or thematic alias should all trigger the confirmation modal consistently

---

### B-004 — mutmut 3.x "0 files mutated" despite scanning 85 files
**Status:** open
**Area:** Testing / Mutation testing

mutmut 3.x scans all source files but finds nothing to mutate:
```
0 files mutated, 0 ignored, 85 unmodified
```

**Investigation done:**
- Verified mutatable functions exist in source (e.g., `calculate_complexity`)
- Checked installed deps: libcst 1.8.6, parso 0.8.6
- Reviewed GitHub issues — no recent reports matching this
- Last mutmut release was Jan 2025 (not a recent regression)
- Hypothesis compatibility fix already in place (`suppress_health_check=[HealthCheck.differing_executors]`)
- No Python version or dependency changes since last successful run

**Version compatibility issue:**
- Config in `pyproject.toml` uses list format for `tests_dir` (3.x style)
- mutmut entered project at >=3.0 and worked previously

**Possible causes:**
- libcst version incompatibility with mutmut's parser expectations
- Code structure changes confusing libcst's AST traversal
- Corrupted mutmut cache (though `mutants/` deletion didn't help)

**Next steps:**
- Try pinning specific libcst version
- Test with minimal example to isolate
- Consider filing issue on mutmut repo

---

### B-005 — Orphaned campaign directories in ~/.unfamiliar/campaigns
**Status:** open
**Area:** Campaign management

Extra "repo-[hash]" directories are being created alongside legitimate campaign folders. Currently 7 orphaned directories vs 3 real repos.

**When it happens:** Possibly during close/reopen campaign workflow (not during normal quit).

**Investigation needed:**
- Trace campaign directory creation logic
- Check if close/reopen is creating duplicates instead of reusing

---

### B-007 — N+1 query patterns in mission unlock path
**Status:** open
**Area:** Campaign / TUI
**Source:** audit DATA-001, QUALITY-007

Two related N+1 patterns:
1. `src/unfamiliar/campaign/missions.py:209-265` (`_unlock_eligible_dependents`) — fetches each prerequisite one-by-one inside a loop.
2. `src/unfamiliar/tui/app.py:328` (`_handle_complete`) — fetches each unlocked mission title with a separate DB call.

**Fix:** Add `get_by_ids(ids: list[int])` to `MissionRepository` and use it in both places.

---

### B-008 — Timestamp columns are nullable with no NOT NULL constraint
**Status:** open
**Area:** Database / schema
**Source:** audit DATA-002

All `created_at TEXT` and `updated_at TEXT` columns in `src/unfamiliar/db/schema.py` (lines 28, 39, 54, 76, 121) are nullable with no DEFAULT. The Python layer always supplies values, but the schema doesn't enforce this. A direct SQL insert or future migration could produce NULLs that crash `datetime.fromisoformat(None)` at read time.

**Fix:** Add `NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))` to all timestamp columns. Requires a schema migration.

---

### B-009 — Module descriptions mismatch with no visibility into discards
**Status:** open
**Area:** Analysis / Module generation

When running on folium repo, the log showed `Have 15 module descriptions, need 64`. This seems excessive.

**Question:** What got discarded? Need a log or readout of what modules were generated vs what was kept to understand the gap.

---

### B-010 — Error when typing "lead" after closing a mission from outro screen
**Status:** open
**Area:** TUI / Mission flow

User has three active missions. Closes one. From the outro screen, types "lead". Expected: navigate to next open mission. Actual: error screen pointing back to investigation screen. This also happens from any screen even if there's only one active mission.

**Steps to reproduce:**
1. Have multiple active missions
2. Complete/close one mission
3. From outro screen, type "lead"
4. Observe error instead of navigation to next mission

---

### B-011 — Mission count discrepancy after completing missions (unlock investigation)
**Status:** open
**Area:** Campaign / Mission unlock
**Source:** deferred.md (Phase 18 UA)

During UA testing: started with 17 available, completed 1 (count stayed 17 — likely 1 unlocked but no toast appeared), completed another (count dropped to 13). The unlock notification fires only if `result.unlocked_ids` is non-empty.

DEBUG logging was added to `_unlock_eligible_dependents()` in Phase 20 but root cause not confirmed.

**Investigation needed:**
- Check if `_unlock_eligible_dependents` is returning empty lists unexpectedly
- Verify toast notification fires correctly when missions unlock
- Test with a campaign that has known prerequisite chains
