diff --git a/README.md b/README.md
index 998abe2..28ed1a7 100644
--- a/README.md
+++ b/README.md
@@ -505,9 +505,16 @@ set APKREV_TOOLS=
; # Windows, e.g. an SDK or proje
export APKREV_TOOLS=: # POSIX
```
-The scripts themselves are plain `python3` and are intended to work identically on Windows, macOS and
+The scripts themselves are plain `python3` and are designed to work identically on Windows, macOS and
Linux; where a snippet is POSIX-only it is labelled. Nothing here assumes a Unix shell.
+**Measured on Windows only.** Every gate run, every test result and every figure in the evidence
+record comes from one host (Windows 10.0.26100, PowerShell 7, CPython 3.14). Cross-platform behaviour
+is a design intention, not an observation: treat another platform as `unverified` until the suite has
+been run there, and expect the usual suspects to be the difference — path separators, `os.pathsep` in
+`APKREV_TOOLS`, console encodings, and shell quoting in the ADB helpers. If you run the gates on
+macOS or Linux and they pass, that is a `observed` result worth recording next to this paragraph.
+
| Tool | Used for |
|---|---|
| Python 3.9+ | all scripts |
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 0e3893e..e0ed8ad 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -417,6 +417,8 @@ export APKREV_TOOLS=: # POSIX
脚本本身是纯 `python3`,并且意图在 Windows、macOS 和 Linux 上行为一致;凡有片段仅限 POSIX,都会标注出来。这里没有任何东西假定你用的是 Unix shell。
+**实测只在 Windows 上做过。** 每一次门禁运行、每一个测试结果、以及证据记录里的每一个数字,都来自同一台主机(Windows 10.0.26100、PowerShell 7、CPython 3.14)。跨平台行为是设计意图,不是观测结果:在别处跑通之前,把另一个平台当作 `unverified`,并预期差异出在几个老地方 —— 路径分隔符、`APKREV_TOOLS` 里的 `os.pathsep`、控制台编码,以及 ADB 辅助脚本里的 shell 引号转义。如果你在 macOS 或 Linux 上跑门禁并通过了,那是一个值得记在这段旁边的 `observed` 结果。
+
| 工具 | 用途 |
|---|---|
| Python 3.9+ | 所有脚本 |
diff --git a/skills/apk-reverse/references/toolchain.md b/skills/apk-reverse/references/toolchain.md
index 1c6e92c..0d3d0e3 100644
--- a/skills/apk-reverse/references/toolchain.md
+++ b/skills/apk-reverse/references/toolchain.md
@@ -270,6 +270,29 @@ line numbers and even which branch is which can differ from the bytecode. When a
it, verify in smali or at runtime. `jadx` writing `(unknown)`/empty method bodies means it failed,
not that the method is empty.
+### A tool that ran out of room did not tell you the target is empty
+
+Every JVM-based reader in this list, and several of the native ones, can die on a large or deeply
+nested input without saying anything about the artifact: `OutOfMemoryError`, a `Killed` from the OOM
+killer, a container limit, or a timeout. The output looks like a tool that read the file and found
+nothing — an empty result plus a line most people skim past.
+
+**What a failed analysis supports is a claim about the analysis, not the artifact**: "this route could
+not complete on this input" is `present but unreadable` (`SKILL.md` §Coverage), and it is exactly
+where a wrong "that class is not in there" gets written into a record. Three things to do before a
+negative from a heavy tool becomes a finding:
+
+- read the **exit code and stderr**, not just stdout — a heap death often exits non-zero with a
+ partial result already printed;
+- give the tool the room the input warrants (a larger heap for the JVM readers) and re-run before
+ concluding anything;
+- prefer a route that does not have to materialise everything: an indexed query against the APK
+ (`rasc`/`droidasc`/`dexsql`) answers most location questions without decompiling a single class, and
+ it is also the route that survives a target too large for a full export.
+
+The same reading applies to a **time budget** you set yourself: a command you killed at your own
+deadline reported nothing about the target, only about your deadline.
+
**`smali` assembling can abort silently** — the tree produces no dex while the process still exits
0. Never treat exit code as proof of a build. Assert the artifact exists, is fresh, and is non-empty
(`patch-audit.md`).