Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
with:
node-version: 22
- name: Shell syntax
run: bash -n deckdoc.sh setup.sh modules/*.sh probe/*.sh bootprobe/*.sh privileged/* tests/*.sh
run: bash -n deckdoc.sh setup.sh lib/*.sh modules/*.sh probe/*.sh bootprobe/*.sh privileged/* tests/*.sh
- name: Regression and safety suite
run: bash tests/test_runner.sh
- name: Documentation links
Expand Down
24 changes: 23 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ All notable DeckDoc changes are recorded here. The project follows

No unreleased changes.

## [3.4.0] - 2026-07-21

### Added

- A versioned model and capability manifest that distinguishes Jupiter LCD, Galileo OLED, unknown
hardware, supported/readable evidence, inaccessible evidence, absence, and non-applicability.
- Shared public-safe filtering for full reports, continuous-probe incidents, remediations, and Rescue
archives, applied before persistent log writes with no intentionally retained raw variant.
- Adversarial privacy fixtures and model fixtures for Jupiter, Galileo, unknown, and inaccessible
evidence states.
- A first-class RyuDeck application adapter that classifies guest startup stalls, active rendering,
stale title-cache suspicion, stalled telemetry, and renderer/process fatal markers without emitting
titles, IDs, paths, arguments, filenames, or raw app-log lines.

### Changed

- Hardware consumers now use discovered DRM, battery, storage, and Wi-Fi paths from the manifest
instead of assuming one fixed device path where discovery is available.
- Core, Steam, filesystem, mount, and block evidence is minimized to diagnostic fields rather than
arbitrary filenames, paths, mount labels, or process inventories.

## [3.3.0] - 2026-07-21

### Added
Expand Down Expand Up @@ -71,7 +92,8 @@ No unreleased changes.

- Initial Steam Deck hardware diagnostic scaffold for GPU, battery, thermals, NVMe, and filesystems.

[Unreleased]: https://github.com/deucebucket/deckdoc/compare/v3.3.0...HEAD
[Unreleased]: https://github.com/deucebucket/deckdoc/compare/v3.4.0...HEAD
[3.4.0]: https://github.com/deucebucket/deckdoc/releases/tag/v3.4.0
[3.3.0]: https://github.com/deucebucket/deckdoc/releases/tag/v3.3.0
[3.2.0]: https://github.com/deucebucket/deckdoc/commit/6d31a545cdb947892d9e6179fb8188d5d26cff88
[3.1.0]: https://github.com/deucebucket/deckdoc/pull/14
Expand Down
47 changes: 28 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DeckDoc

**Current source release: v3.3.0** · [Changelog](CHANGELOG.md) ·
**Current source release: v3.4.0** · [Changelog](CHANGELOG.md) ·
[Roadmap](ROADMAP.md) · [DeckMD](https://deucebucket.github.io/deckdoc/) ·
[Diagnostic wiki](https://github.com/deucebucket/deckdoc/wiki)

Expand All @@ -9,13 +9,14 @@ larger question behind almost every Deck failure: **what actually failed, what e
conclusion, and what is the safest next action?**

It collects and correlates evidence across the APU/GPU, memory, storage and filesystems, battery and
power, thermals and fan, Wi-Fi, audio, controls, Steam and Proton, Gamescope, suspend/resume, display,
USB-C docks, and connected peripherals. It can capture a one-time system snapshot, preserve evidence
from intermittent failures, inspect a docked hardware path, or collect from outside the installed OS.
The result is one timestamped case that can separate likely application/configuration faults,
SteamOS or driver faults, peripheral faults, and evidence that warrants hardware escalation.

The project currently ships 17 read-only diagnostic modules, an opt-in incident probe, dock/USB-C
power, thermals and fan, Wi-Fi, audio, controls, Steam and Proton, Gamescope, applications,
suspend/resume, display, USB-C docks, and connected peripherals. It can capture a one-time system
snapshot, preserve evidence from intermittent failures, inspect a docked hardware path, diagnose a
supported app's own structured runtime, or collect from outside the installed OS. The result is one
timestamped case that can separate likely application/configuration faults, SteamOS or driver faults,
peripheral faults, and evidence that warrants hardware escalation.

The project currently ships 19 read-only diagnostic modules, an opt-in incident probe, dock/USB-C
analysis, an alpha rescue collector/image builder, a guided symptom checker, a diagnostic wiki, and
two tightly guarded remediations. DeckDoc is diagnosis-first: its coverage is intentionally much
broader than the small number of conditions it can safely change automatically.
Expand All @@ -33,6 +34,7 @@ paths as you answer, and keeps the complete grouped checklist behind **Browse al
|---|---|
| Boot and stability | Did the Deck fail before SteamOS, panic, freeze, restart, or lose only one service? |
| Games and graphics | Did one title fail, did Gamescope restart, or did the AMD GPU fault and recover? |
| Applications | Did a supported app fail before launch, reach its runtime but stop producing work, rebuild stale state, or record a renderer/process fatal? |
| Memory and crashes | Was there an OOM kill, active pressure, swap churn, or a relevant new core dump? |
| Storage | Is the NVMe or microSD reporting health, controller, filesystem, TRIM, or read-only errors? |
| Power and thermals | Are battery, charging, PMIC, fan, temperature, or low-frequency signals abnormal? |
Expand Down Expand Up @@ -61,32 +63,35 @@ sudo ./deckdoc.sh
```

Reports are written under `logs/`. The file named `deckdoc_master_report_<timestamp>.log` is the
combined report; `module_*.log` files contain each subsystem's raw section.
combined report; `module_*.log` files contain public-safe filtered subsystem sections, and
`deckdoc_capabilities_<timestamp>.json` records the model and evidence-access contract.

Before posting a report publicly, read [Collecting and sharing evidence](docs/wiki/Collecting-and-Sharing-Evidence.md).
Network names/addresses, usernames, paths, process names, and game titles may be present.
All collection modes filter credentials and common personal/device/network identifiers before any
persistent log write, and do not keep an intentionally raw variant. Because upstream log formats can
change, review a report before posting it. See
[Collecting and sharing evidence](docs/wiki/Collecting-and-Sharing-Evidence.md).

## One project, five diagnostic modes

| Mode | Best for | Output |
|---|---|---|
| Full report | Current system-wide snapshot | 17 correlated module logs plus one master report |
| Full report | Current system-wide snapshot | Capability manifest, 18 subsystem logs, and one master report |
| Continuous probe | Rare/transient failures | Trigger, pre/post journal window, and volatile incident state |
| Dock A/B | Third-party dock, PD, USB, Ethernet, display failures | Topology, exported negotiation, connector, and reset evidence |
| DeckDoc Rescue | Installed OS cannot boot or needs an outside-OS contrast | Private read-only rescue archive and installed journal image evidence |
| DeckDoc Rescue | Installed OS cannot boot or needs an outside-OS contrast | Public-safe read-only rescue archive and installed journal image evidence |
| DeckMD + wiki | User does not know which subsystem to test | Ranked symptom branches, known patterns, safe checks, and escalation route |

## Core commands

| Command | Effect | Changes the system? |
|---|---|---|
| `sudo ./deckdoc.sh` | Run all 17 diagnostic modules | No; creates local logs |
| `sudo ./deckdoc.sh` | Run all 19 diagnostic modules | No; creates local logs |
| `./deckdoc.sh` | Run with reduced access | No; some checks may be incomplete |
| `sudo ./probe/install-probe.sh install` | Opt in to the low-overhead incident watcher | Yes; installs/starts one constrained service |
| `sudo ./probe/install-probe.sh uninstall` | Stop/remove watcher, preserving incidents | Yes; service files only |
| `sudo ./bootprobe/deckdoc-rescue-collect.sh ...` | Collect outside-OS evidence from a compatible rescue environment | No writes to installed disk; creates private archive |
| `sudo ./bootprobe/deckdoc-rescue-collect.sh ...` | Collect outside-OS evidence from a compatible rescue environment | No writes to installed disk; creates a filtered archive |
| `sudo ./privileged/install-authorized.sh install` | Approve DeckDoc's exact read-only privileged operations once | Yes; root-owned snapshot and narrow sudoers rules |
| `./privileged/deckdoc-authorized-client.sh report` | Run a complete authorized report later without sharing a password | No; creates a private local report |
| `./privileged/deckdoc-authorized-client.sh report` | Run a complete authorized report later without sharing a password | No; creates a filtered local report |
| `bash tests/test_runner.sh` | Run mocked regression tests | No production-device changes |

The optional authorization does not give DeckDoc—or an agent—a password or general sudo access. It
Expand All @@ -99,6 +104,7 @@ snapshot or changing that allowlist requires another visible user approval. See

| Area | Module | Evidence and signatures |
|---|---|---|
| System contract | `system_manifest.sh` | model/OS allowlist, LCD/OLED applicability, discovered devices, readable/inaccessible/absent evidence states |
| GPU/APU | `gpu_apu.sh` | amdgpu ring timeouts, reset outcome, low CPU/GPU frequency state |
| Display | `display_blackout.sh` | eDP status, EDID, backlight, CRTC, DRM planes, Gamescope, display warnings |
| Dock/USB-C | `dock_usb_c.sh` | USB topology, Type-C/PD/Alt Mode exports, external displays, Ethernet, path errors |
Expand All @@ -113,6 +119,7 @@ snapshot or changing that allowlist requires another visible user approval. See
| Memory | `memory_swap.sh` | MemAvailable, swap use, cumulative vs live I/O, current-boot OOM events |
| Incident history | `probe_incidents.sh` | latest opt-in trigger, volatile snapshot, bounded journal window |
| Steam/Proton | `steam_client_logs.sh` | real crash files, helper crash rate, Steam errors, prefix/lock inventory |
| App runtime | `ryudeck_app.sh` | RyuDeck install/profile state, runtime stage, FPS progress, cache/pipeline signals, renderer/process fatal classes |
| microSD | `mmc_sd_card.sh` | mmc presence/mounts, driver/ext4/TRIM errors, read-only state |
| Suspend/resume | `acpi_pm_state.sh` | PM transitions/failures, fan-controller warnings, wake sources |
| Vulkan translation | `dxvk_page_fault.sh` | AMD VM/UTCL2 page-fault class, process hints, timeouts, reset result |
Expand Down Expand Up @@ -154,7 +161,7 @@ The full interpretation guide is [Reading DeckDoc reports](docs/wiki/Reading-Dec

## Diagnosis first, narrow remediation second

DeckDoc's main product is evidence and decision support. Seventeen modules, the probe, Rescue, DeckMD,
DeckDoc's main product is evidence and decision support. Eighteen modules, the probe, Rescue, DeckMD,
and the wiki diagnose far more conditions than DeckDoc modifies. Only two signature-specific
remediations exist today:

Expand Down Expand Up @@ -189,12 +196,14 @@ CPU/GPU clocks, charging behavior, firmware, or GPU-reset sysfs nodes. See the

```text
deckdoc.sh
|-- launches 17 diagnostic modules in parallel
|-- flushes module output into logs/module_*.log
|-- discovers the model/capability contract first
|-- launches 18 subsystem modules in parallel
|-- filters every module before writing logs/module_*.log
|-- consolidates a timestamped master report
`-- dispatches explicit remediation modes sequentially

modules/ diagnostic and remediation shell modules
lib/ shared public-safe output filtering
probe/ opt-in event-triggered watcher and constrained service installer
bootprobe/ outside-OS collector and unsigned alpha ArchISO builder
privileged/ one-time approved, exact-command diagnostic broker
Expand Down
22 changes: 14 additions & 8 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# DeckDoc v3.3.0 roadmap — full-system diagnostics and incident response
# DeckDoc v3.4.0 roadmap — full-system diagnostics and incident response

DeckDoc's product is evidence, correlation, and safe decision support. It should help a user separate
application/configuration faults, SteamOS/driver faults, accessory or dock faults, and strong hardware
Expand All @@ -9,8 +9,9 @@ narrow and is not the measure of project coverage.

| Capability | Current state |
|---|---|
| Full report | 17 read-only modules across GPU, power, thermal, storage, filesystems, audio, display, docks, crashes, Wi-Fi, Gamescope, memory, probe history, Steam, microSD, resume, and GPU page faults |
| Incident probe | Opt-in bounded event capture prototype; private, resource-limited, no remediation |
| Full report | Model/capability manifest plus 18 read-only subsystem modules across GPU, power, thermal, storage, filesystems, audio, display, docks, crashes, Wi-Fi, Gamescope, memory, probe history, Steam, RyuDeck app health, microSD, resume, and GPU page faults |
| Application diagnostics | First privacy-safe RyuDeck adapter separates host initialization, guest progress, cache/pipeline behavior, rendering, and fatal runtime classes; the adapter contract is intended to extend to other apps |
| Incident probe | Opt-in bounded event capture prototype; public-safe filtered, resource-limited, no remediation |
| Dock analysis | USB/Type-C/PD/Alt Mode/display/Ethernet evidence and current-boot path-error correlation |
| DeckDoc Rescue | Read-only collector plus unsigned ArchISO alpha builder for outside-OS comparison |
| DeckMD | Public, static, local-only checker with six guided categories, contradiction pruning, 128 facts, and 15 ranked branches |
Expand All @@ -23,7 +24,9 @@ narrow and is not the measure of project coverage.
### [#15 Model and capability manifest](https://github.com/deucebucket/deckdoc/issues/15)

Identify model, OS/build/slot, drivers, devices, and supported evidence sources before interpreting
their presence or absence. Modules must not assume LCD/OLED behavior, device indices, or driver names.
their presence or absence. The schema-v1 Jupiter/Galileo/unknown baseline and first dynamic-path
consumers shipped in v3.4.0; remaining modules, Rescue semantics, OS-slot data, and schema compatibility
remain tracked here.

### [#17 Unified timeline and access ledger](https://github.com/deucebucket/deckdoc/issues/17)

Expand All @@ -32,8 +35,9 @@ Normalize boot IDs, time scopes, sources, events, and permission/retention state

### [#22 Safe redacted bundle and storage-risk gate](https://github.com/deucebucket/deckdoc/issues/22)

Stop normal writes when storage evidence threatens data, then produce separate private/raw and reviewed,
redacted bundles without automatic upload.
Stop normal writes when storage evidence threatens data. v3.4.0 filters every normal capture before
disk and intentionally retains no raw variant; a formal share-bundle gate, storage-risk gate, and
continued adversarial review remain.

## P1 — productionize the new diagnostic modes

Expand All @@ -57,8 +61,10 @@ redacted bundles without automatic upload.
- Bluetooth, HID, Steam Input, touch, gyro, and controller lifecycle without logging raw input;
- SteamOS update, slot, image, immutable-root, free-space, and previous-image health.

Future coverage should also add structured JSON output, battery trend baselines, performance timelines,
firmware/recovery contrasts, and an upstream-ready issue packet built from the redacted bundle.
Future coverage should also extend structured JSON beyond the capability manifest, add battery trend
baselines, performance timelines, firmware/recovery contrasts,
[additional first-party application adapters](https://github.com/deucebucket/deckdoc/issues/27), and
an upstream-ready issue packet built from the redacted bundle.

## Remediation policy

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.3.0
3.4.0
33 changes: 20 additions & 13 deletions bootprobe/deckdoc-rescue-collect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ set -uo pipefail

umask 077

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REDACTOR="${SCRIPT_DIR}/../lib/deckdoc-redact.sh"
if [ ! -x "$REDACTOR" ]; then
echo "DeckDoc public-safe output filter is missing; refusing collection." >&2
exit 1
fi

OUTPUT_ROOT="/tmp"
INSTALLED_DISK="/dev/nvme0n1"
while [ "$#" -gt 0 ]; do
Expand All @@ -23,7 +30,8 @@ Usage: deckdoc-rescue-collect.sh [--output-dir PATH] [--installed-disk /dev/DEVI

Collects live rescue-environment evidence and attempts read-only journal extraction from the installed
disk through journalctl --image. It never mounts, repairs, unlocks, or writes the installed disk.
The resulting archive is private and unredacted. /tmp is volatile; copy it before powering off.
The archive is public-safe filtered before disk write, but should still be reviewed before sharing.
/tmp is volatile; copy it before powering off.
EOF
exit 0
;;
Expand Down Expand Up @@ -59,9 +67,9 @@ run_section() {
echo "rescue_boot_id=$(cat /proc/sys/kernel/random/boot_id 2>/dev/null || echo inaccessible)"
echo "installed_disk=${INSTALLED_DISK}"
echo "collection_policy=read-only-no-mount-no-repair"
echo "privacy=private-unredacted"
echo "privacy=public-safe-filtered-review-before-sharing"
echo "transport=copy archive to removable media or transfer over authenticated docked Ethernet"
} > "${CASE_DIR}/manifest.txt"
} | "$REDACTOR" > "${CASE_DIR}/manifest.txt"

{
run_section "kernel" uname -a
Expand All @@ -72,8 +80,7 @@ run_section() {
done
run_section "PCI devices and drivers" lspci -nnk
run_section "USB topology" lsusb -t
run_section "block topology" lsblk -o NAME,PATH,TYPE,TRAN,SIZE,RO,FSTYPE,FSVER,LABEL,MOUNTPOINTS
run_section "mounts" findmnt -lo SOURCE,TARGET,FSTYPE,OPTIONS
run_section "block topology" lsblk -o NAME,PATH,TYPE,TRAN,SIZE,RO,FSTYPE,FSVER

echo "--- Type-C and PD exports ---"
for port in /sys/class/typec/port[0-9]*; do
Expand Down Expand Up @@ -102,31 +109,31 @@ run_section() {
done
run_section "network link inventory" ip -details -brief link
run_section "USB Ethernet candidates" sh -c 'for n in /sys/class/net/*; do [ -d "$n" ] || continue; printf "%s driver=%s state=%s\n" "$(basename "$n")" "$(basename "$(readlink -f "$n/device/driver" 2>/dev/null || echo unknown)")" "$(cat "$n/operstate" 2>/dev/null || echo inaccessible)"; done'
} > "${CASE_DIR}/live-hardware.log" 2>&1
} 2>&1 | "$REDACTOR" > "${CASE_DIR}/live-hardware.log"

{
run_section "rescue current-boot journal" journalctl -b 0 -o short-iso-precise --no-pager
run_section "rescue kernel ring" dmesg -T
if [ -d /sys/fs/pstore ]; then run_section "pstore inventory" find /sys/fs/pstore -maxdepth 1 -type f -printf '%f %s bytes\n'; fi
} > "${CASE_DIR}/live-journal.log" 2>&1
} 2>&1 | "$REDACTOR" > "${CASE_DIR}/live-journal.log"

{
run_section "NVMe smartctl" smartctl -x "$INSTALLED_DISK"
if command -v nvme >/dev/null 2>&1; then run_section "NVMe smart log" nvme smart-log "$INSTALLED_DISK"; fi
run_section "block read-only flags" lsblk -o NAME,PATH,RO,SIZE,FSTYPE,MOUNTPOINTS "$INSTALLED_DISK"
} > "${CASE_DIR}/storage-health.log" 2>&1
run_section "block read-only flags" lsblk -o NAME,PATH,RO,SIZE,FSTYPE "$INSTALLED_DISK"
} 2>&1 | "$REDACTOR" > "${CASE_DIR}/storage-health.log"

{
echo "DeckDoc uses systemd's image reader; it does not mount or repair the installed filesystems."
run_section "installed boot index" journalctl --image="$INSTALLED_DISK" --list-boots --no-pager
} > "${CASE_DIR}/installed-boot-index.log" 2>&1
} 2>&1 | "$REDACTOR" > "${CASE_DIR}/installed-boot-index.log"

{
run_section "installed previous boot" journalctl --image="$INSTALLED_DISK" -b -1 -o short-iso-precise --no-pager
run_section "installed current/last boot" journalctl --image="$INSTALLED_DISK" -b 0 -o short-iso-precise --no-pager
} > "${CASE_DIR}/installed-journals.log" 2>&1
} 2>&1 | "$REDACTOR" > "${CASE_DIR}/installed-journals.log"

if command -v efibootmgr >/dev/null 2>&1; then efibootmgr -v > "${CASE_DIR}/uefi-boot-entries.log" 2>&1 || true; fi
if command -v efibootmgr >/dev/null 2>&1; then efibootmgr -v 2>&1 | "$REDACTOR" > "${CASE_DIR}/uefi-boot-entries.log" || true; fi

(
cd "$CASE_DIR" || exit 1
Expand All @@ -137,4 +144,4 @@ chmod 600 "$ARCHIVE"
sha256sum "$ARCHIVE" > "${ARCHIVE}.sha256"

echo "DeckDoc Rescue capture complete: ${ARCHIVE}"
echo "This archive is unredacted. Review it before sharing, and copy it out of /tmp before shutdown."
echo "This archive was public-safe filtered before disk write. Review it before sharing, and copy it out of /tmp before shutdown."
Loading
Loading