# v5.7.0 Manual Verification Checklist

Use this list to validate the v5.7.0 global-variable enforcement work end-to-end before merging PR #169 and tagging the release. The automated suites cover the rules layer; this checklist exercises the live endpoints against a real Ghidra session.

Most steps are scripted by `tests/integration/test_global_endpoints.py`. The list below documents the same checks for cases where you want to do them by hand (e.g., spot-checking the rejection messages on a specific binary).

## Prerequisites

- Ghidra 12.1 running with a binary loaded (D2Game.dll in the dev environment).
- `python -m tools.setup verify-version` reports **5.7.0**.
- The v5.7.0 plugin has been deployed to Ghidra. If you haven't deployed yet:
  ```text
  python -m tools.setup deploy --ghidra-path "F:\ghidra_12.1_PUBLIC" --test release
  ```
  Per-CLAUDE.md, the graceful sequence is: `save_program` → `exit_ghidra` → wait → run deploy.

## Automated checks

```text
# Java offline rules (53 tests; should all pass)
mvn test -Dtest=NamingConventionsTest

# Live endpoint integration (16 tests; auto-skips on v5.6.x, runs on v5.7.0+)
pytest tests/integration/test_global_endpoints.py -v --no-cov

# Full release floor
python -m tools.setup verify-version
python -m tools.setup build
pytest tests/unit/ -v --no-cov
mvn test -Dtest='com.xebyte.offline.*Test'
```

## Manual checks

### 1. `audit_global` returns a structured issues list

Pick any data address in your binary. The integration suite uses `list_data_items` to find one; for manual checks pick a known global like `DAT_*` or a previously-named one.

```text
GET /audit_global?address=0x6fdf64d8&program=/Mods/PD2-S12/D2Game.dll
```

Expected: 200 OK. Body has `address`, `name`, `type`, `length`, `plate_comment`, `xref_count`, `issues`, `fully_documented`. The `issues` list should be empty for a fully-documented global; otherwise it contains zero or more of `generic_name`, `untyped`, `unformatted_bytes_length_mismatch`, `unformatted_bytes_should_be_string`, `missing_plate_comment`, `plate_comment_too_short`.

### 2. `rename_data` validator rejection

```text
POST /rename_data
{"address": "0x6fdf64d8", "newName": "dwSomething"}
```

Expected: 200 OK with `{"status":"rejected","error":"name_quality","issue":"missing_g_prefix",...}`. The rejected name was NOT applied (verify with `audit_global` after).

Repeat with each rejection code:

| Bad name | Expected `issue` |
|---|---|
| `dwActiveQuestState` | `missing_g_prefix` |
| `g_DAT_6fdf64d8` | `auto_generated_remnant` |
| `g_PTR_DAT_1234` | `auto_generated_remnant` |
| `g_dw_6fdf64d8` | `auto_generated_remnant` |
| `g_ActiveState` | `missing_hungarian_prefix` |
| `g_dwX` | `short_descriptor` |
| `g_pUnitCount` (when type is `uint`, not pointer) | `prefix_type_mismatch` |

### 3. `set_global` atomic write — happy path

Write all four axes at once:

```text
POST /set_global
{
  "address": "0x6fdf64d8",
  "name": "g_pDifficultyLevelsBIN",
  "type_name": "uint",
  "plate_comment": "Pointer to the DifficultyLevels.bin table loaded at startup."
}
```

Expected: `{"status":"success","applied":["type","name","plate_comment"]}`. A subsequent `audit_global` should report `fully_documented: true` (or have only `unformatted_bytes_*` issues if the array length wasn't right).

### 4. `set_global` rejects with no partial write

This is the critical contract — when ANY rule fails, NOTHING applies.

```text
POST /set_global
{
  "address": "0x6fdf64d8",
  "name": "g_pSomethingValid",
  "type_name": "undefined4",
  "plate_comment": "Some valid plate comment line here."
}
```

Expected: `{"status":"rejected","error":"undefined_type_rejected",...}`.

Verify by `audit_global` before and after — the name and plate-comment must be unchanged.

### 5. `set_global` rejects each rule independently

| Bad input | Expected `error` |
|---|---|
| `name: "DAT_1234"` | `name_quality` (issue: `auto_generated_remnant`) |
| `type_name: "undefined4"` | `undefined_type_rejected` |
| `type_name: "ThisDoesNotExist"` | `unknown_type` |
| `plate_comment: "counter"` (1 word) | `plate_comment_too_short` |
| `plate_comment: "global counter"` (2 words) | `plate_comment_too_short` |

### 6. `set_global` array_length applies the array variant

```text
POST /set_global
{
  "address": "0x6fdf6358",
  "type_name": "uint",
  "array_length": 16,
  "name": "g_anItemMaxStack",
  "plate_comment": "Per-item-id maximum stack sizes loaded from ItemTypes.bin."
}
```

Expected: `applied: ["type", "array_length=16", "name", "plate_comment"]`. The Ghidra Listing now shows 16 typed `uint` elements at the address.

### 7. `set_global` empty payload is a no-op success

```text
POST /set_global
{"address": "0x6fdf64d8"}
```

Expected: `{"status":"success","applied":[]}`. No state change; no error. Lets the model probe without side effects.

### 8. Step prompt loads with the new module

In the worker pane (or `fun-doc/fun_doc.py` directly), the next FULL or recovery prompt build should include `step-globals.md` between `step-type-audit.md` and `step-comments.md`. Smoke check via the dashboard: start a worker; the visible output should reference the global-quality bar / `audit_global` / `set_global` when documenting a function with global xrefs.

## Pass criteria

All of:
- Java offline + Python unit + Python integration (post-deploy) suites green.
- Manual rejection-table walks through rows 1-7 above without surprise.
- `audit_global` on a known-fully-documented global reports `fully_documented: true`.
- `set_global` partial-application test (#4) confirms no state leaked through on rejection.
- Workers running on v5.7.0 produce documentation that flips global-related deductions on a sample function.

## Additional checks (v5.7.0 — full scope)

### 9. `audit_globals_in_function` per-function bulk auditor

```text
GET /audit_globals_in_function?address=0x6fcab220&program=...
```

Expected: 200 OK with `{function: {address, name}, globals: [...], summary: {total, fully_documented, with_issues, issue_histogram}}`. The summary's `fully_documented + with_issues` should equal `total`, and `len(globals)` should match `total`. Picks up only data references (skips call/jump/flow refs and addresses inside the function's own body).

### 10. Per-function global-quality scorer deductions surface in work items

Pick a function that references `DAT_*` globals. Run `analyze_function_completeness` on it. The result's `deduction_breakdown` should include one or more of: `untyped_global`, `unformatted_global_bytes`, `generic_global_name`, `missing_global_plate_comment`. Aggregate cap is -20 pts so 20 broken globals don't dominate the score.

### 11. Bulk `global_scorer` daemon

Open the dashboard. The new "Global Inventory (v5.7.0)" panel sits directly below "Inventory (Scoring Coverage)". Click **Enable**. The scorer should:

- Walk every binary in the project tree.
- For each binary, call `list_globals` then audit each via `audit_global`.
- Tally `total_documentable` / `fully_documented` per binary; persist to `fun-doc/global_inventory.json`.
- Yield (paused) when any doc worker is active.
- Update the dashboard panel live via `global_inventory_status` WebSocket events.

After ~30s with the scorer enabled, the table should populate at least one row. Coverage bars, percent, and status columns should render.

### 12. `step-globals.md` is loaded into doc-worker prompts

Start a doc worker. The next FULL or recovery prompt should include the `step-globals.md` module text — search the worker output for "audit_globals_in_function" mention. If you don't see it, the prompt builder isn't wiring the new module.
