# scj-hunt — changelog

The Gigi-fiber vulnerability hunter for Windows drivers. Format
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); each
release pairs a researcher-facing summary with the file-level diff
that landed it.

All releases ship against the prod Gigi surface at
`https://gigi-stream.fly.dev` and the canonical SCJ corpus
(`scj_vid_v01_prod` + side bundles).

## [Unreleased]

## [v0.5] — 2026-06-07

The "researchers stop second-guessing the checklist" release. Everything
on the REACHABILITY CHECKLIST that can be auto-evaluated, now is —
each item shows a verdict (☑/☐/☒) plus the evidence trail that
produced it. The evidence pack gets a geometrist-grade layout pass
so continuation lines actually align.

### Added
- **Auto-evaluated reachability checklist** (`tui::checklist`) — 7
  items, each with `Verdict::{Yes, No, Unknown}` + evidence string +
  optional `hint`. Section header shows `N/7 auto-verified`.
  - Items 1, 2 (IOCTL / hypercall ancestry): 8-hop backward BFS over
    the loaded callgraph; matches `*DispatchDeviceControl*`,
    `*HvCall*`, `*VmCall*`, etc.
  - Items 4, 5, 6 (bounds check / safe-math / probe): scan loaded
    excerpts for `RtlULongMult`, `__builtin_mul_overflow`,
    `ProbeForRead/Write`, and `if (param/size/Length cmp …)` patterns.
  - Item 7 (guest-reachable driver): static allowlist of 10 curated
    Hyper-V drivers with per-driver attack-surface annotation.
  - Item 3 (taint): stays Unknown, but emits a per-signature-bit
    hint pointing at what to look for in the caller chain.
- **`e` binding on Registry + GQL pane** opens DEFINE PATTERN prefilled
  with the highlighted pattern. Auto-jumps focus to Registry; status
  line reads `editing <name>`.
- **`Enter` on Results opens evidence pack** — previously only `o`
  worked. The inline keymap footer always said `↵ / o · evidence`
  so the code was just lying.

### Changed
- **Evidence pack visual rework** (`tui::views::evidence_full`)
  - Section headers now green (`theme.fg`), not yellow — yellow is
    reserved for the warning banner and risk score so the eye lands
    on actual signal.
  - ALLOC-SITE EXCERPT matched line is now a **solid yellow callout
    strip** (bg=accent, fg=term_bg, padded to `inner_w`) instead of
    just yellow text. Every strip is the same width regardless of
    code length.
  - Header bar split into left (binary id) + right (action chrome:
    `candidate (v0.5) · ↓ scroll · Esc back · w write · y copy GQL`).
  - Cross-references truncated to top 5 callers/callees + `+N more`
    — no more multi-line wrapping in CROSS-REFERENCES.
  - Geometrist pass: `Wrap { trim: false }` killed; every line is
    pre-truncated to `inner_w` with `…` suffix; continuation lines
    indent to col 7 (under the evidence text). No content ever
    reflows to col 0 anymore.
  - Blank line between checklist items for vertical rhythm.
- **Results selection** — removed `row_highlight_style` (was layering
  yellow-fg on yellow-bg, making text invisible); per-cell styling
  now wins. Selected row is yellow bg + dark fg + bold, readable.
- **Inline keymap footer per pane:**
  - Registry: `↵ run hunt · ↑↓ navigate · n new pattern · e edit pattern`
  - Gql: `↑↓ scroll · e edit pattern · y copy` (was `↑↓ scroll` only)

### Fixed
- Selected RESULTS row was yellow-on-yellow — text invisible while
  highlighted.
- Tape 05 referenced `vid_all_functions.json` which doesn't exist;
  retargeted to `hvsocket_all_functions.json` with a relative path
  that resolves from `scj-hunt/docs/tapes/`.

### Tests
- 7 new unit tests in `tui::checklist` — guest-reachable allowlist,
  safe-math hit, IOCTL chain BFS, taint-hint-per-bit, count-excludes-
  unknown, edge cases.

### Infrastructure
- `.github/workflows/scj-hunt-ci.yml` — fmt, clippy `-D warnings`,
  build, test on every PR + push to main.
- `.github/workflows/scj-hunt-tapes.yml` — renders all 6 tapes on
  `ubuntu-latest` against prod Gigi (uses `secrets.GIGI_API_KEY`),
  uploads MP4 artifact, commits back on main.
- ~~`.github/workflows/scj-hunt-pages.yml`~~ — written, but the repo's
  GitHub plan doesn't support Pages (HTTP 422 from `POST /repos/{owner}/{repo}/pages`).
  Removed from the tree; re-add when the repo goes public or the plan
  upgrades.
- **Known issue:** GitHub Actions runs against this private repo's
  current plan fail with `startup_failure` and no logs (typically
  means the free private-repo Actions minutes are exhausted, or an
  org-level policy blocks runs). The workflows are syntactically
  valid (pass `python -c "import yaml; yaml.safe_load(open(...))"`
  and the inline render path); they'll execute once the plan side is
  resolved. Verify locally via `scripts/build_tapes.sh` (Linux/macOS)
  or WSL with the chromium libs installed.
- All 7 tapes switched from `.gif + .mp4` dual output to **MP4 only**
  — H.264 is ~10× smaller than GIF palette for terminal capture,
  sharper, and plays inline in GitHub READMEs.
- WSL-friendly `scripts/build_tapes.sh` rewrite — `cd`s into the
  tapes dir before invoking vhs (relative `Output` paths resolve),
  accepts multiple tape prefixes, wraps each render in a 5-min timeout.
- Honest platform-support matrix in `scj-hunt/docs/tapes/README.md`
  (✅ Linux/macOS, ⚠️ WSL2-with-libs, ❌ Windows native — vhs hangs
  on Windows; ttyd ↔ Chrome connection bug upstream).

## [v0.4] — 2026-06-07 (earlier)

Mockup-parity rework. The 3-pane v0.3 layout flips to the 4-pane
topology from `specs/SCJ_HUNT_TUI_v0.4.md`:

`BUNDLES | HUNT REGISTRY | GQL` on top, `RESULTS` full width below.

### Added
- **BUNDLES pane** — left-most strip, lists code corpora on the bound
  Gigi instance (filtered to drop `_calls`, `_excerpts`, `_taint`,
  `_smoke_`, `_test_`, `_gigi_*` internals). `★` marker on the active
  bundle. `R` refreshes; `Enter` swaps.
- **GQL pane** — top-right, shows the compiled query produced by the
  current pattern selection (read-only — patterns drive what's
  executed; you edit a pattern to change the GQL).
- **Full-screen evidence view** — Enter/`o` on a results row replaces
  the browse layout entirely (was a centered modal overlay). Sections:
  IDENTITY, RISK SIGNAL, RISK SCORE BREAKDOWN, CROSS-REFERENCES,
  ALLOC-SITE EXCERPT, REACHABILITY CHECKLIST, CONFIRMED-BUG XREF,
  POC TRIGGER VALUE, MSRC SUBMISSION READINESS.
- **`path_length` + `forward_taint` on every row** — client-side
  callgraph BFS on a fresh bundle bind (`tui::reachability`); no
  Python pipeline integration. `forward_taint = 1 / (1 + distance)`
  as a heat-kernel proxy. Visible in RESULTS REACH/PATH columns.
- **Scope-aware inline keymap footer** — replaces the opaque status
  footer. Each pane gets its own legend strip (`↵ run hunt · ↑↓
  navigate · n new pattern` on Registry, etc.) plus globals.
- **In-TUI ingest** via `:ingest <path>` — drops a Ghidra JSON export
  to Gigi as `scj_<module>_v01_prod`; BUNDLES refreshes.
- **Two-step `x` review confirmation** — first press asks, second
  commits. Prevents accidental marks.

### Changed
- RESULTS columns rebuilt to mockup parity: `#, RVA, FUNCTION, RISK,
  REACH, PATH`. REACH is `YES`/`NO` based on callgraph; PATH is
  `caller → function` (or `self (topological entry)`).
- Tab cycle: `Bundles → Registry → Gql → Results → Bundles`.

## [v0.3]

### Added
- Hunt history (`H` key) — recent hunt list with re-run on Enter.
- Pattern composition — AND / OR / NOT combinators across patterns.
- Runtime DEFINE PATTERN modal (`n` key) with live autocomplete
  dropdown for fiber field names; Ctrl+S POSTs to `/v1/patterns`.
- CWE category per row — `infer_cwe_from_bits()` maps signature bit
  sets to canonical CWE codes.
- Symbol resolution (PDB + Ghidra) for `FUN_xxxxxxx` → real names.
- Multi-pattern hunt — combine N patterns in one query.

## [v0.2.7] — visual pass

- Rounded borders + title chrome on all panes.
- Full-row selection highlight in RESULTS.
- Compact 5-cell score bar visualization in the RISK column.
- Inline syntax highlighting on patterns view.
- DEFINE PATTERN modal + autocomplete dropdown (mockup screen 2).

## [v0.2.5]

- Sort results by column (`s` cycles score → size → sinks).
- Export — CSV of displayed results, evidence-pack markdown of
  highlighted row.
- Bundle switching from the TUI (`:bundle <name>`).
- Mark-as-reviewed → push to `false_positives` persistent set.
- Pattern parameters / scoped hunts (`size_min`, `size_max`, etc).

## [v0.2]

- Score-breakdown row inspector — which bits + sinks contributed
  how much to the final score.
- `/` filter / search — live narrowing of the displayed result set.
- Cross-references (callers ← / callees →) populated from the
  `_calls` side bundle.
- Body display — literal source excerpts around each matched site
  from the `_excerpts` side bundle.
- PoC scaffold overlay — generates a stub PoC payload for the
  highlighted candidate.

## [v0.1]

- Initial TUI skeleton: 3 panes (patterns, results, detail).
- Theme + empty-screen render, help overlay.
- Prod Gigi integration (gigi-stream.fly.dev, X-API-Key auth).
