summaryrefslogtreecommitdiffstats
path: root/docs/05-operations/04-green-eye-user-guide.md
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-02 11:44:31 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-02 11:44:31 -0400
commit1c99bfbeffff04529f6f669601fdf835a73778da (patch)
tree5867bab46e5848541df36c703f6fd8d6d0256e54 /docs/05-operations/04-green-eye-user-guide.md
parent2fd653044127a665e4677a2cdfb58120d7b3e16b (diff)
downloadopen-iov-1c99bfbeffff04529f6f669601fdf835a73778da.tar.gz
open-iov-1c99bfbeffff04529f6f669601fdf835a73778da.zip
rename (cosmetic): green-eye -> risc-v-gsp-rm-debugger in user-facing names, docs, CLI, launcher and CI workflow; internal greeneye package/module identifiers unchanged (includes in-flight greeneye module edits present in the tree)
Diffstat (limited to 'docs/05-operations/04-green-eye-user-guide.md')
-rw-r--r--docs/05-operations/04-green-eye-user-guide.md439
1 files changed, 0 insertions, 439 deletions
diff --git a/docs/05-operations/04-green-eye-user-guide.md b/docs/05-operations/04-green-eye-user-guide.md
deleted file mode 100644
index a9bf1dc..0000000
--- a/docs/05-operations/04-green-eye-user-guide.md
+++ /dev/null
@@ -1,439 +0,0 @@
-# green-eye User Guide (experimental)
-
-> **# TOOL IN DEVELOPMENT - NOT READY YET!**
-> green-eye is the development environment for running GSP/uproc firmware
-> off-hardware, observing it, injecting into it and comparing runs as evidence.
-> It is never shipped, never a driver dependency and never present in a guest;
-> interfaces and file formats may change without notice. For incident response
-> procedures see the [Open-IOV Defensive Operations Runbook](../RUNBOOK.md).
-
-This guide is the single front door for a new user: what green-eye is, how to
-get a first recorded run in ten minutes, which tool to use for which task, how
-to treat sessions as evidence, and what to do when something is wrong. The
-authoritative details live in the tool's own documentation set
-([documentation map](#10-documentation-map)).
-
-## 1. What green-eye is
-
-green-eye runs GSP/uproc firmware in a controllable machine, instruments it
-with Frida-like primitives, records a durable session, changes the machine's
-inputs (including injected code), and compares runs so that emulation changes
-in `open-iov-vfio` land with evidence instead of anecdotes.
-
-| It is | It is not |
-|---|---|
-| A firmware runtime microscope (execution + memory: L0/L1) | A timing, interrupt or device model (L2/L3 absent) |
-| A scriptable `Session` API with two backends (QEMU-RSP and native) | A GDB wrapper; there is no GDB dependency |
-| A recorded-evidence system with a versioned session format | A product component, a guest agent or a shipped dependency |
-| A static/dynamic join for Ghidra | A decompiler or a CUDA-corpus replacement |
-| An automation layer (harnesses, MCP, CI) | A fuzzing service against hardware; simulator/re-hosted code only |
-
-Ghidra answers *what is the code*; green-eye answers *what did it do*. Guest
-diagnostics answer *what did the driver request*; a supervised physical cycle
-answers *what does silicon do*. green-eye makes the middle question repeatable
-and safe.
-
-## 2. Ten-minute quickstart
-
-Requirements: Linux, Python 3.10+ (stdlib only), `qemu-system-riscv64`
-(Ubuntu `qemu-system-misc`), `clang` and `lld`. No GPU, no driver and no
-kernel module are touched.
-
-```bash
-cd open-iov/debug/risc-v-gsp-rm-vm
-
-./greeneye.sh info # environment check: QEMU, toolchain, paths
-make demo && make sdk # build the bundled RV64 uproc demo and injection SDK
-
-./greeneye.sh demo # canned run: boot, hooks, watchpoints, session
-./greeneye.sh analyze dumps/<printed-session-dir>
-
-./greeneye.sh probe # real GSP image: report the first divergence
-./greeneye.sh inject # load and invoke a position-independent service
-```
-
-What "good" looks like:
-
-1. `info` reports QEMU and the demo paths;
-2. `demo` prints hook/branch lines and a session directory under `dumps/`;
-3. `analyze` renders hook/watch/breakpoint events and a coherent summary;
-4. `probe` reports a bounded first divergence (for the TU104 570.144 image, a
- load-access fault at firmware vaddr `0x4009014` reading
- `0x2000000000000A00`) — that is expected data, not a boot;
-5. `inject` returns matching values on the direct and firmware-dispatched
- paths.
-
-Next steps: [choose a tool](#5-choosing-the-right-tool) for your task and read
-[Common recipes](#7-common-recipes).
-
-## 3. Mental model
-
-### 3.1 Two backends, one session API
-
-```text
-CLI / REPL / Python ─┐
-MCP (stdio) ────────┼─► GreenEyeAPI ─► Session ─┬─► QEMU-RSP backend (qemu-system-riscv64)
-Ghidra bridge ──────┤ hooks, watchpoints, └─► native backend (sim/machine.py)
-harness/ + rmharness┘ memory, symbols, recorder ──► session directory
-```
-
-* **QEMU-RSP** is the default: full RV64 execution, gdbstub transport without
- GDB, TCG trace plugin optional.
-* **native** (`--backend native`) is the in-process interpreter: deterministic
- virtual time (instruction counts), fast startup, an exec/access trace, and
- lenient MMIO for first-touch exploration.
-* Both satisfy the same `Session` primitives (registers/memory, breakpoints,
- watchpoints, step/continue, snapshots), so scripts, probes, plugins,
- recordings and comparisons survive a backend change.
-
-### 3.2 The primitives
-
-| Primitive | Use it for |
-|---|---|
-| `breakpoint` / `hook` | did this function run? with what arguments and return value? |
-| `watch` (`w`/`r`/`a`) | when did this field change, from which store PC? |
-| `run` / `run_until` | bounded observation; stop at a chosen address |
-| `call` | Frida-like remote call to unit-test a function in isolation |
-| `step` / `note` | single-step with dispatch; annotate the event stream |
-| `Memory.read/write/hexdump/search/snapshot/diff` | inspect and diff memory regions |
-| `SymbolDB` | resolve file/program/runtime addresses across sources |
-| `Recorder` | write the durable session (events, snapshots, blobs) |
-| injection SDK | load, register and invoke your own PIC RV64 service |
-
-Instructions between stops are invisible unless a trace is on: the TCG plugin
-(`-plugin qemu/greeneye-trace.so`) on QEMU, or `--trace` on the native backend.
-
-### 3.3 Fidelity levels (what a result can mean)
-
-| Level | Property | green-eye today |
-|---|---|---|
-| **L0** | instruction semantics | high (QEMU TCG, same ISA family) |
-| **L1** | memory behaviour | high for RAM-resident code, conditional on mapping |
-| **L2** | time/concurrency | **not modelled** (do not claim) |
-| **L3** | device environment (falcon, WPR2, CSB, PMU, timers, DMA, IRQ) | **absent** (device model is roadmap) |
-
-A simulator observation is evidence about the firmware, not about silicon;
-anything that would change the product is reproduced on a physical/vfio-mdev
-reference first. Never quote a green-eye session for timing, interrupt or
-security claims.
-
-### 3.4 A session is the unit of work
-
-Every run records a `greeneye-session/1` directory:
-
-```text
-dumps/<stamp>-<name>/
- session.json format, name, counts, snapshot inventory, meta
- events.jsonl append-only event stream (hooks, watches, memory, notes)
- snapshots/*.bin.z zlib-compressed region captures with sha256
- blobs/* QEMU logs, trace.jsonl, host-oracle stdout
- summary.md rendered analysis
-```
-
-Partial sessions stay readable; the format evolves additively. A copied
-`events.jsonl` without its `session.json`, snapshots and metadata is not
-evidence.
-
-## 4. Tool inventory
-
-Run everything from `open-iov/debug/risc-v-gsp-rm-vm/` unless stated.
-
-### 4.1 CLI (`./greeneye.sh`)
-
-| Command | One-line purpose |
-|---|---|
-| `info` | environment/tooling check (QEMU, paths, capabilities) |
-| `demo` | canned boot + hooks + watchpoints + recording on the bundled uproc |
-| `run <script.py>` | run a Python instrumentation session against the demo/ELF |
-| `attach` / `launch` | interactive REPL; keep a target alive and print its gdbstub port |
-| `record` | boot and record with watches/snapshots (and `--trace` on native) |
-| `probe <image>` | bounded run of a raw image; first-divergence report |
-| `analyze <session>` | session to symbol-annotated Markdown report |
-| `compare <a> <b>` | symbolic A/B delta of two recorded sessions |
-| `symbols export\|resolve` | build/inspect a runtime-address symbol DB |
-| `inject` | load, register and invoke an SDK service (direct + mailbox) |
-| `ghidra` | serve the live session to GhidraScripts over localhost |
-| `plugins` | list discoverable plugins |
-
-### 4.2 Harnesses (`harness/`)
-
-| Tool | One-line purpose |
-|---|---|
-| `portability_matrix.py` | probe + fixed scenario + compare across targets, with an M1–M6 skeleton |
-| `mutation_harness.py` | seeded one-input mutations with outcome classes and per-attempt sessions |
-| `control_discovery.py` | sweep a call surface to find known/unknown/injected handler IDs |
-| `reach.py` | is one symbol reachable, what triggers it, with what arguments and effects |
-| `version_diff.py` | old vs new image: shape, symbols, corpus hints, probe, behavior |
-| `ci_release.py` | version_diff → matrix → mutation smoke, hashed into one bundle |
-| `port_driver_versions.py`, `port_new_device.py`, `package_sim.py` | porting/packaging scaffolds (dry-run default; pilot status and evaluation in [docs/28](../../debug/risc-v-gsp-rm-vm/docs/28-PORTING-AUTOMATION.md), [docs/29](../../debug/risc-v-gsp-rm-vm/docs/29-PACKAGING-AND-TRIALING.md)) |
-| `value_demos/run_all.py` | ten fixed scenarios s01–s10 with measured time-to-value |
-| `common.py` | shared helpers (flat relocation, sessions, bounded log reads) |
-
-### 4.3 Native simulator, plugins, host oracle, bridges
-
-| Tool | One-line purpose |
-|---|---|
-| `sim/` (`--backend native`, `--trace`) | deterministic RV64IMAC interpreter with exec/access trace and lenient MMIO |
-| `python3 -m greeneye.device_map harvest\|show\|merge\|demo` | first-touch MMIO map: authoring, inspection, merge |
-| `qemu/greeneye_trace.c` (`make -C qemu`) | full TCG exec/access JSONL trace with `start=`/`end=` filters |
-| `plugins/example_plugin.py` | plugin authoring reference |
-| `plugins/mcp_server.py` | MCP server for agents (stdio or loopback; read-only by default) |
-| `plugins/rmharness_plugin.py` | REPL commands for the host RM oracle |
-| `rmharness/harness.sh` + `rmtool`/`rmtop`/`rmq` | read-only host oracle captures appended into a session |
-| `ghidra/ExportForGreenEye.java`, `MarkGreenEyeHits.java`, `GreenEyeControl.java` | symbol export, hit annotation and decompiler-driven execution |
-| `sdk/` + `greeneye inject` | position-independent service ABI v1 |
-
-## 5. Choosing the right tool
-
-| Task | Tool | Notes |
-|---|---|---|
-| "Does this run?" / first divergence of a raw image | `./greeneye.sh probe` | no device model: expected early fault is data |
-| "What does this firmware do on this stimulus?" | `record` / `run` + `analyze` | fixed stimulus, bounded budgets, hooks/watchpoints |
-| "Which command IDs exist / what is undiscovered?" | `harness/control_discovery.py` | fresh session per probe; deterministic seed |
-| "Is this function reachable, and how?" | `harness/reach.py` | `auto|stimulus|trigger|run|call`; emits a replayable probe spec |
-| "What changed between two firmware versions?" | `harness/version_diff.py`, `./greeneye.sh compare` | static inventory + dynamic profile |
-| "Does the new firmware move behaviour or code?" | `harness/version_diff.py` + docs/14 decision table | code vs behaviour classification |
-| "Prove an error path / fail-closed rule" | `harness/mutation_harness.py` | simulator only; seeded and replayable |
-| "Prototype an RM service before product code" | `sdk/` + `./greeneye.sh inject` | PIC blob; direct and mailbox paths |
-| "Join Ghidra static addresses to runtime hits" | `./greeneye.sh ghidra` + Java bridges | localhost only; no auth |
-| "What does a control reply look like on real RM?" | `rmharness/harness.sh … rmtool` | read-only host oracle; safe beside a CUDA job |
-| "Explore MMIO the firmware touches first" | `probe` → `python3 -m greeneye.device_map` | versioned JSON; feeds the device model |
-| "Triage a release end to end" | `harness/ci_release.py` | always `--dry-run` first |
-| "Let an agent monitor a run" | `plugins/mcp_server.py` | read/observe by default; writes gated |
-
-Decision rule: static reading is a hypothesis; a recorded session is evidence;
-at least an A/B pair is a conclusion.
-
-## 6. Sessions as evidence
-
-1. **Record with a fixed stimulus.** The same script, seed, budgets and image
- hash make runs comparable; a self-comparison must be empty.
-2. **Annotate as you go.** `s.note(...)` inside the session explains what was
- asked and what was mutated; a chat log is not evidence.
-3. **Attach the provenance.** Firmware SHA-256, version string, pairing notes,
- symbol DB source/hash/bias, and the exact command or script.
-4. **Keep the directory together.** `session.json` + `events.jsonl` +
- `snapshots/` + blobs are one artifact; publish a SHA-256 list when moving
- it.
-5. **State the fidelity.** L0/L1 exercised; L2/L3 not claimed; reference
- capture named (hardware, vfio-mdev, host oracle or none).
-6. **Report deltas honestly.** `compare` marks non-semantic fields (time, host
- paths, backend identity) as such; every remaining delta is explained or
- listed as open. An empty unexplained-delta list is a claim that must be
- earned.
-7. **Bundle for triage.** A release bundle is
- `bundle-manifest.json` + `release-report.json` + version-diff + portability
- matrix + mutation smoke; see
- [docs/21](../../debug/risc-v-gsp-rm-vm/docs/21-CI-RELEASE-PIPELINE.md) §4.3.
-
-The M1–M6 metric contract (inventory, reply, ordering, state, error-path and
-memory-side-effect agreement) is defined in
-[docs/06-ACCURACY](../../debug/risc-v-gsp-rm-vm/docs/06-ACCURACY.md) §5 and is
-authoritative for every claim.
-
-## 7. Common recipes
-
-### 7.1 First record and analyze
-
-```bash
-cd debug/risc-v-gsp-rm-vm
-make demo
-./greeneye.sh demo # prints the session directory
-./greeneye.sh analyze dumps/<session> # symbol-annotated report
-```
-
-### 7.2 Probe a new firmware image
-
-```bash
-./greeneye.sh symbols export --index <export.tsv> --bias 0 -o symbols-<ver>.json
-./greeneye.sh probe <gsp-<VER>.fwimage.bin> --symbols symbols-<ver>.json --record
-python3 harness/version_diff.py --old <old> --new <new> --out dumps/vdiff-<ver> \
- --old-symbols symbols-<old>.json --new-symbols symbols-<new>.json
-```
-
-### 7.3 Discover controls and prove reachability
-
-```bash
-python3 harness/control_discovery.py --out dumps/discovery --max-id 32 \
- --patterns zero --seed 5
-python3 harness/reach.py --target rpc_ping --method call --args 0x41 \
- --out dumps/reach-ping
-```
-
-### 7.4 Mutate an input surface (simulator only)
-
-```bash
-python3 harness/mutation_harness.py --out dumps/mutation-7 \
- --iterations 64 --seed 7 --timeout 0.25 --settle 0.2
-```
-
-### 7.5 Portability pipeline across targets
-
-```bash
-python3 harness/portability_matrix.py \
- --target <reference-fwimage> --target <candidate-fwimage> \
- --out dumps/matrix-candidate --probe-instructions 200 --scenario-duration 0.2
-```
-
-### 7.6 Inject and debug a service
-
-```bash
-make -C sdk
-make -C sdk relocs
-./greeneye.sh inject --service sdk/build/injected_demo.elf --cmd 1 --arg0 0x41 --arg1 0x42
-```
-
-The direct call is the unit test; the mailbox call is the integration test.
-Both are recorded.
-
-### 7.7 Drive execution from Ghidra
-
-```bash
-# terminal 1
-./greeneye.sh ghidra --kernel <elf> --bridge-port 7000
-# terminal 2 (Ghidra headless)
-$GHIDRA/support/analyzeHeadless <proj> <name> -process <program> -noanalysis \
- -scriptPath open-iov/debug/risc-v-gsp-rm-vm/ghidra \
- -postScript GreenEyeControl.java 7000 0x<address>
-```
-
-### 7.8 Host oracle capture (read-only)
-
-```bash
-./rmharness/harness.sh --session dumps/real-<anchor> --name before \
- -- rmtool engine list --format=json
-./rmharness/harness.sh --session dumps/real-<anchor> -- rmtop --once
-```
-
-### 7.9 Release rehearsal
-
-```bash
-python3 harness/ci_release.py --old <old> --new <new> --out dumps/release-<ver> \
- --old-label <OLD> --new-label <NEW> --dry-run
-```
-
-`--dry-run` prints the plan and creates nothing; the RM 610 gate refuses 610
-labels (exit 3) until a human approves in writing.
-
-### 7.10 Let an agent monitor
-
-```bash
-python3 plugins/mcp_server.py --stdio --backend native --record
-# read/observe by default; --allow-write and --allow-inject are explicit opt-ins
-```
-
-### 7.11 First-touch device map
-
-```bash
-./greeneye.sh probe <fwimage> --record
-python3 -m greeneye.device_map harvest dumps/<probe-session> --out dumps/<ver>-device-map.json
-python3 -m greeneye.device_map show dumps/<ver>-device-map.json
-```
-
-## 8. Troubleshooting
-
-| Symptom | Likely cause | Fix |
-|---|---|---|
-| `qemu-system-riscv64 not found` | QEMU absent or not on `PATH` | install `qemu-system-misc` or point `GREENEYE_QEMU` at the binary |
-| QEMU starts but the script cannot attach | wrong port / target exited | use the port `launch`/`demo` printed; re-run `launch` and `attach --port <port>` |
-| `Address already in use` on a bridge/trace port | stale bridge or another session | choose another `--bridge-port`; check `pgrep -fa greeneye` and `pgrep -fa qemu-system-riscv64` |
-| QEMU survives Ctrl-C of a script | `launch` keeps the target alive by design | close the session or stop the reported PID; do not kill an unrelated QEMU |
-| Session analyzer shows no hits/events | recording off, or the stimulus never ran | use the CLI (records by default); check hooks/watchpoints with a known symbol (`rpc_sum`) |
-| `NameError: __file__` in `run` scripts | script invoked outside `greeneye.sh run` | run through `./greeneye.sh run`, keep scripts inside the tool tree |
-| Empty TCG trace blob | plugin window missed or target never resumed | `make -C qemu`; widen `start=`/`end=`, set `exec=on`, resume the target |
-| MCP writes refused / no tools | server read-only by default; stdout polluted | pass `--allow-write`/`--allow-inject` deliberately; keep stdout protocol-only |
-| `greeneye error:` on a valid path | wrong relative path or `--db` file | `./greeneye.sh info` shows resolved paths; bad symbol DBs fail with a clear error |
-| Harness findings not reproducible | seed/budget changed | pin `--seed` and budgets; compare `findings.jsonl` byte-for-byte |
-| Everything "unreachable" | wrong surface/timeouts | run `--surface demo` on the built demo first; raise `--settle`/`--timeout` |
-| `Unknown symbol` in the optional OpenRM build | module-tag drift | re-pin build glue; see the [RUNBOOK](../RUNBOOK.md) S2 |
-
-Marker status: every tool document carries the
-**# TOOL IN DEVELOPMENT - NOT READY YET!** banner. The marker is removed only
-when the acceptance list in
-[docs/00-OVERVIEW](../../debug/risc-v-gsp-rm-vm/docs/00-OVERVIEW.md) passes on a
-clean checkout, the usage recipes verify end-to-end, a second person can run
-the quickstart unaided, and the session format and CLI are declared stable.
-
-## 9. Safety
-
-* **Simulator only.** The tools launch their own QEMU or native machine
- against the bundled demo or an explicitly allowed re-hosted ELF. They never
- attach to hardware, a guest, a kernel module, an mdev or an existing
- gdbstub.
-* **No guest, no hardware, no product.** Nothing runs in a guest; injected
- services are prototypes, not shipped code; product changes go through
- `open-iov-vfio` with physical confirmation.
-* **Read by default; writes gated.** MCP `write_mem`/`call_function` need
- `--allow-write`, injection needs `--allow-inject`, and every write is
- recorded in the session.
-* **Bounded everywhere.** Runs have durations/stop caps; reads and snapshots
- have size caps; harness subprocesses have timeouts; a wedged target is left
- stopped and restarted clean rather than poked.
-* **Local only.** Ghidra and MCP transports are localhost/stdio; the bridge is
- unauthenticated by design, so never expose it on a network interface.
-* **No confidentiality claims.** The simulator is a study environment, never a
- security or confidentiality boundary; never use injection to defeat a
- hardware security boundary.
-* **Fuzzing is gated.** Mutation runs only against the simulator or re-hosted
- code, behind explicit harnesses, with recorded evidence.
-* **RM 610 is a hard human gate.** No acquisition, analysis, emulation edit,
- physical work or support claim before written approval; the gate is enforced
- by the CLIs.
-
-## 10. Documentation map
-
-Tool documentation (`debug/risc-v-gsp-rm-vm/docs/`): [00 overview](../../debug/risc-v-gsp-rm-vm/docs/00-OVERVIEW.md),
-[01 design](../../debug/risc-v-gsp-rm-vm/docs/01-DESIGN.md),
-[02 usage](../../debug/risc-v-gsp-rm-vm/docs/02-USAGE.md),
-[03 scripting](../../debug/risc-v-gsp-rm-vm/docs/03-SCRIPTING.md),
-[04 plugins](../../debug/risc-v-gsp-rm-vm/docs/04-PLUGINS.md),
-[05 Ghidra bridge](../../debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md),
-[06 accuracy](../../debug/risc-v-gsp-rm-vm/docs/06-ACCURACY.md),
-[07 portability playbooks](../../debug/risc-v-gsp-rm-vm/docs/07-PORTABILITY-PLAYBOOKS.md),
-[08 roadmap](../../debug/risc-v-gsp-rm-vm/docs/08-ROADMAP.md),
-[09 firmware notes](../../debug/risc-v-gsp-rm-vm/docs/09-GSP-FIRMWARE-NOTES.md),
-[10 related work](../../debug/risc-v-gsp-rm-vm/docs/10-RELATED-WORK.md),
-[11 RM service guide](../../debug/risc-v-gsp-rm-vm/docs/11-GSP-RM-SERVICE-DEVELOPER-GUIDE.md),
-[12 injection SDK](../../debug/risc-v-gsp-rm-vm/docs/12-INJECTION-SDK.md),
-[13 Ghidra control](../../debug/risc-v-gsp-rm-vm/docs/13-GHIDRA-CONTROL.md),
-[14 adversarial interop](../../debug/risc-v-gsp-rm-vm/docs/14-ADVERSARIAL-INTEROP-GUIDE.md),
-[15 agentic GSP IDE](../../debug/risc-v-gsp-rm-vm/docs/15-AGENTIC-GSP-IDE.md),
-[16 custom simulator](../../debug/risc-v-gsp-rm-vm/docs/16-CUSTOM-SIMULATOR.md),
-[17 RM harness](../../debug/risc-v-gsp-rm-vm/docs/17-RM-HARNESS.md),
-[18 harness automation](../../debug/risc-v-gsp-rm-vm/docs/18-HARNESS-AUTOMATION.md),
-[19 control discovery](../../debug/risc-v-gsp-rm-vm/docs/19-CONTROL-DISCOVERY.md),
-[20 MCP server](../../debug/risc-v-gsp-rm-vm/docs/20-MCP-SERVER.md),
-[21 CI/release pipeline](../../debug/risc-v-gsp-rm-vm/docs/21-CI-RELEASE-PIPELINE.md),
-[22 porting CUDA and devices](../../debug/risc-v-gsp-rm-vm/docs/22-PORTING-CUDA-AND-DEVICES.md),
-[23 RM 610 readiness](../../debug/risc-v-gsp-rm-vm/docs/23-RM610-READINESS.md),
-[24 device map](../../debug/risc-v-gsp-rm-vm/docs/24-DEVICE-MAP.md),
-[25 value validation](../../debug/risc-v-gsp-rm-vm/docs/25-VALUE-VALIDATION.md),
-[26 architecture](../../debug/risc-v-gsp-rm-vm/docs/26-ARCHITECTURE.md),
-[27 tool audit](../../debug/risc-v-gsp-rm-vm/docs/27-TOOL-AUDIT.md),
-[28 porting automation](../../debug/risc-v-gsp-rm-vm/docs/28-PORTING-AUTOMATION.md),
-[29 packaging and trialing](../../debug/risc-v-gsp-rm-vm/docs/29-PACKAGING-AND-TRIALING.md), and the
-[long-term roadmap](../../debug/risc-v-gsp-rm-vm/GREEN-EYE-ROADMAP.md).
-
-Project documentation:
-
-* [Open-IOV Defensive Operations Runbook](../RUNBOOK.md) — incident scenarios
- S1–S10, evidence bundles, escalation tree;
-* [GSP in a RISC-V VM](03-risc-v-gsp-rm-vm.md) — project-level purpose, status
- and limits;
-* [Debugging and maintenance workflows](02-debugging-and-maintenance-workflows.md)
- — captures, failure taxonomy and the upgrade runbook;
-* [Hardware and software matrix](../06-portability/hardware-software-matrix.md)
- — support ladder and the portability pipeline;
-* [Adversarial interoperability](../04-implementation/02-practical-challenges-and-adversarial-interop.md)
- — the no-patch rule;
-* [Engineering operations](../eng-ops.md) — tool admission, workflows and
- retirement (the cross-cutting engineering-operations document);
-* CUDA playbook:
- [`userspace/cuda/docs/07-version-upgrade-playbook.md`](../../userspace/cuda/docs/07-version-upgrade-playbook.md)
- and [`userspace/cuda/READ-ME-FIRST.md`](../../userspace/cuda/READ-ME-FIRST.md);
-* [Documentation front door](../README.md) — the full reading order.
-
-<!-- change (2026-10-02): correct the TCG plugin filename to the actual
-qemu/greeneye_trace.c, list the docs 28/29 scaffolds in the tool inventory and
-documentation map; scope: §4.2, §4.3, §10 only; benefit: copied commands and
-doc-map navigation match the tool tree. -->