docs+analysis: independent verification guide for phases A-F (calibrated scanners, self-tested commands)
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
import java.util.stream.*;
|
||||
|
||||
/**
|
||||
* Cross-check the quoted DebugLog lines in docs/android_app/real_device_checklist.md
|
||||
* against the Kotlin sources, so a verifier can confirm the checklist describes
|
||||
* logs the code can actually produce.
|
||||
*
|
||||
* WHY NOT A PLAIN SEARCH: the sources build messages by interpolation
|
||||
* ("$name write=$n/${packet.size}") while the checklist shows instantiated
|
||||
* examples ("GetParameter1 write=4/4"). A literal search therefore produces
|
||||
* false negatives. This tool instead (1) tries the literal with <placeholders>
|
||||
* removed, then (2) falls back to requiring the remaining identifier-ish words
|
||||
* to appear somewhere in the sources.
|
||||
*
|
||||
* A "needs review" line means the whole message is instance data (the template
|
||||
* lives in one string literal and the command name is a call-site argument) —
|
||||
* those must be traced by hand to the call site. Both categories were manually
|
||||
* resolved for the 2026-09-11 run (see verification_guide.md §3 Phase A).
|
||||
*
|
||||
* Usage:
|
||||
* java CheckStrings.java docs/android_app/real_device_checklist.md android/app/src/main
|
||||
*/
|
||||
public class CheckStrings {
|
||||
public static void main(String[] a) throws Exception {
|
||||
String md = Files.readString(Paths.get(a[0]), java.nio.charset.StandardCharsets.UTF_8);
|
||||
StringBuilder src = new StringBuilder();
|
||||
try (Stream<Path> s = Files.walk(Paths.get(a[1]))) {
|
||||
List<Path> kt = s.filter(x -> x.toString().endsWith(".kt")).collect(Collectors.toList());
|
||||
for (Path p : kt) src.append(Files.readString(p, java.nio.charset.StandardCharsets.UTF_8)).append('\n');
|
||||
}
|
||||
String all = src.toString();
|
||||
|
||||
// only lines that show a DebugLog tag: [usb] [vm] [session] [cmd] [stream] [pip] [remote] [crash]
|
||||
Matcher m = Pattern.compile("`(\\[(?:usb|vm|session|cmd|stream|pip|remote|crash)\\][^`]*)`").matcher(md);
|
||||
int exact = 0, skeleton = 0, miss = 0;
|
||||
Set<String> seen = new LinkedHashSet<>();
|
||||
List<String> misses = new ArrayList<>();
|
||||
|
||||
while (m.find()) {
|
||||
String line = m.group(1);
|
||||
if (!seen.add(line)) continue;
|
||||
// the tag is a separate DebugLog argument in the source
|
||||
String msg = line.replaceFirst("^\\[[a-z]+\\]\\s*", "");
|
||||
|
||||
String literal = msg.replaceAll("<[^>]*>", "").trim();
|
||||
if (literal.length() >= 6 && all.contains(literal)) { exact++; continue; }
|
||||
|
||||
String skel = msg
|
||||
.replaceAll("<[^>]*>", " ")
|
||||
.replaceAll("0x[0-9A-Fa-f]+", " ")
|
||||
.replaceAll("\\b\\d+(\\.\\d+)?\\b", " ")
|
||||
.replaceAll("[A-Za-z]*\\d[A-Za-z0-9]*", " ")
|
||||
.replaceAll("[^\\x20-\\x7E\\u4e00-\\u9fff]+", " ");
|
||||
List<String> keep = new ArrayList<>();
|
||||
for (String w : skel.trim().split("\\s+")) {
|
||||
if (w.length() >= 3 && w.matches("[A-Za-z_:.\\-\\[\\]()/]+")) keep.add(w);
|
||||
}
|
||||
boolean found = !keep.isEmpty();
|
||||
for (String w : keep) if (!all.contains(w)) found = false;
|
||||
if (found) skeleton++;
|
||||
else { miss++; misses.add(line + " [probe: " + String.join(" ", keep) + "]"); }
|
||||
}
|
||||
|
||||
System.out.println("exact literal match : " + exact);
|
||||
System.out.println("skeleton match : " + skeleton);
|
||||
System.out.println("needs human review : " + miss);
|
||||
if (!misses.isEmpty()) {
|
||||
System.out.println();
|
||||
for (String s : misses) System.out.println(" ? " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user