Software Litigation Consulting

Andrew Schulman
Consulting Technical Expert & Attorney

Software Litigation Consulting

Software Litigation Consulting (Andrew Schulman; undoc@sonic.net) specializes in source code examination, software reverse engineering, pre-filing investigation of software/internet patent infringement, the preparation of claim charts (infringement, non-infringement, invalidity, and validity contentions), and research in software prior art. Currently working with Claude to build a CodeExam tool, and using AI chatbots to finish work on a Patent Litigation book.

Too busy working with Claude (Opus 4.5 and 4.6 Enhanced) since Jan. 22, 2026, to write up the experience of developing large CodeExam tool with this shockingly-good collaborator, nor to write about the CodeExam tool itself. For now, just sharing some of the chat transcripts (sometimes with a claude.ai/share URL, other times a txt file), most recent first. I’ll soon describe CodeExam, and provide some annotations to the Claude chat transcripts below, including looking at Claude’s “chain of thought” and tool use:

  • Switched to Claude Code, thanks to Jon Udell; various fixes, as described by Claude Code in Git commits (TODO: show transcript for 1 or 2 of these, from my vague description of problem, to Claude’s fix and Git commit, to give flavor of working with Claude Code):
    • Make CodeExam into an MCP (Model Context Protocol) engine, so that AI (including local LLM Qwen 3.0, with no internet connection) can provide an AI chatbot about the indexed source code.
    • Prototyping dynamic GUI, based on the user’s needs; starting with popup window with side-by-side comparison of multiple functions that are struct-dupes or near-dupes; and making call-tree and file-map mermaid diagrams interactive: clicking on nodes and edges creates popups
    • Render /file-map as Mermaid diagram in GUI console
    • Add diagram depth control to GUI
    • Add filesystem browser to Load Index dialog
    • Fix Indexes accordion: file counts, isLoaded, dir scanning, confirm dialog
    • Add left pane pop-out and accordion overflow fade indicator
    • Make Claim/Multisect workspace prominent with pop-out support
    • Add filter support to all duplicate lists and show filter in fullscreen
    • Fix false class attribution in callees [fix not complete; class disambiguation in static code analysis is hard problem]
  • CodeExam GUI, connecting LLM search/analyze” (in progress, see screenshot at CodeExam page)
  • CodeExam GUI design with HTMX or XMLUI” (txt; TODO: expand Claude CoT “>” then re-save text, to provide sample of lengthy periods of working, tool-use, writing code, testing)
  • CodeExam Node.js port development roadmap” (txt)
    • Indexing of source-code tree from zip/tar/gz/etc. archive (7z to come).
    • Indexing of binary executable files (exe, dll, sys, so, pyd, etc.), with strings (and demangled C++ function signatures) turned into pseudo-functions in .op files.
    • Class::method disambiguation for callees; nice test_disambiguation.js covering about a dozen scenarios; a few issues still TODO.
    • –multisect-search (and therefore related multisect-analyze, claim-search, claim_analyze) now looks for classes in which substantially all terms appear; so preference is now for hits within single function, then hits across multiple methods within single class (possibly distributed over multiple fles), then hits across multiple functions in same file, and finally hits across multiple files in same folder.
    • –call-inventory command to list all calls, including to an external source not in the codebase (RTL, API, missing code, etc.); basically a call-target symbol table; joins –entry-points and –gaps (list code implemented without a caller in the codebase).
    • Continued testing on massive codebases
  • Vocabulary-guided patent claim term extraction” (txt)
    • Using the codebase’s vocabulary (from –discover-vocabulary) to guide extraction of terms from patent claim text.
    • Testing extraction of terms with local LLM, Qwen Coder, and use of –vocab-tight for local LLMs.
    • New –follows-calls and –deep commands to have –extract show not only named function, but also its callees.
    • New –comments-only option to –extract command, to show only full-line comments from a function; works with –follows-calls to generate nice trees of major source-code comments; all followed by a caveat that says “Tip: Comments can lie! Verify against actual code logic.”
  • CodeExam Node.js phase 8a complete, phase 8b planning” (txt)
    • Continuing port of code from Python to Node.js
    • Finish –multisect-search command (looks for interection of all search terms, in narroest location: first in function, then across multiple functions in same file/class, then in multiple files in same folder; includes NOT terms, regex).
    • Finish –multisect-analyze command (takes top 2 functions returned from multisect-search, and passes to LLM for analysis; for air-gapped source-code analysis under PO, can use local LLM; right now, using Qwen-Coder: qwen2.5-coder-7b-instruct-q4_k_m.gguf).
    • Finish –claim-analyze command (takes patent claim text, passes to LLM to extract terms [both tight and broad, with synonyms], then does –multisect-analyze with tight and broad terms to get LLM analysis of top 2 functions from multisect-search; LLM analysis done in context of patent claim text and extracted tight/broad terms).
    • End to end pipeline now working with local LLM: patent claim text -> local LLM extracts terms -> multisect search to locate two best matching functions matching terms -> pass functions + original claim text to local LLM -> get back analysis.
    • Comparing analyses from local DeepSeek-Coder vs. local Qwen-Coder vs. Claude.
    • Qwen-Coder is current favorite local LLM model for code, over DeepSeek-Coder and CodeLlama.
    • Nice discussion of “the wonder of local LLMs” (how an essentially static 4GB file of floating-point numbers can input English + code, and can output an analysis in English of the code; more surprising than fact that an online LLM like Claude, with massive infrastructure behind it, can do this; discussion of node-llama-cpp).
    • Both PY and JS code include lengthy English-language prompts for LLMs.
    • Initial JS port of function masking from PY (right now only removing comments from code before passing to LLM; in full PY implementation, masking almost all names/symbols to force LLM analysis to rely on code, not lean on comments/naming)
    • Miscellaneous fixes re: –discover-vocabulary, –list-functions, –extract-function
    • Discussion of using –discover-vocabulary feature to extract terms from claim similar to source code’s nomenclature.
  • Wrapping up multisect-search phase 5 port” (txt)
    • Porting –multisect-search feature from PY to JS (identify functions or files or folders meeting substantially all of a list of semicolon-delimited terms, including synonyms for terms, and NOT terms)
    • Add –in filter to search-related commands, e.g. search for pivot –in excel
    • “Term selectivity” in multisect search, compared to TF-IDF in –discover-vocabulary
    • Show correct function/file/class context for search hits
    • Modify search to look in path/filename as well as file contents
  • Node.js port continuation and feaure implementation summary” (txt)
    • Porting dupe and de-duplication features from PY to JS
    • Four levels of dupe testing: verbatim (SHA1-hashed) files; verbatim (SHA1-hashed) function bodies; “structurally-identical” function bodies (using Abstract Syntax Tree [AST], without operands, as structure); “near-dupes” (functions with identical filename/size, but SHA1 of function body differs)
    • –struct-diff and –struct-diff-all to show changes across structurally-identical but not verbatim-identical functions, and across near-dupes
    • Improved class::method detection, including inferring class from calls-to, even without declaration (works for . as well as :: separator)
    • Improved language-specific regex (but will be moving to tree-sitter, already worked well in PY)
  • Converting Python code to Node.js
    • Claude creates 9-phase strategy for Node.js port (noting existing JSON-based persistence allows direct compatibility between Python-built indexes and the new Node.js tool).
    • Delivery of Phase 1 and 2 of the JS port (core index building, literal/inverted search, call-tree, and file-map functionality, maintaining zero external npm dependencies).
    • Overcoming Node.js hard size limits (bypassing 536MB string and 2GB buffer limits by building a chunked `FileScanner` and streaming JSON parser to load massive 5GB+ Chromium source-code indexes).
    • Prioritizing Phase 6 Interactive REPL (keeping multi-gigabyte indexes in memory across multiple slash commands like `/hotspots` and `/classes` to avoid long load times).
    • Fixing V8 heap out-of-memory errors (keeping the 2.9GB inverted index on disk to stream on-demand, introducing lazy parsing and result caching for instant subsequent queries).
    • Fixing regex patterns for C++ parsing (capturing Chromium’s multi-line method signatures in .cc files where return types or arguments wrap across lines).
    • Planning for future features (–discover-vocabulary for sweet-spot token filtering to find domain jargon, and loading zip/tar archive files).
  • Code exam claim search parameter issue” (txt)
    • Discussion of ChromaDB semantic search limitations (explaining why standard natural language embedding models perform poorly on source code without intermediate AI summarization).
    • Rebuilding ce_analyze.py (restoring the full 2,000-line pipeline from analyze_bridge.py to bring back the automated extraction and analysis features).
    • Successful end-to-end pipeline validation (confirming the full flow of passing claim text, extracting terms via LLM, running multisect search, and having the LLM accurately analyze the resulting functions).
    • Clarification of –claim-analyze design intent (resolving the architectural difference between the original “manual” workflow of passing a known function name to the LLM, versus fully-automated pipeline that searches for code at least in same ballpark as patent claim text, auto-picks the top hit, and analyzes that)
  • Refactoring code search into modular architecture
  • Collaborative software source code investigation
    • Claude and I use the CodeExam tool to answer a question about how Moltbook authenticates its users are bots, not humans; we end up at Twitter/X OAuth
  • call-tree and file-map implementation
  • Connecting extract and analyze pipeline with command variants
  • Air-gapped tool demo index and search-analyzer integration
  • Updating TODO master file incrementally
  • Code exam, part 4
  • Air-gapped source code analysis tool development” (part 3)
  • Code exam, part 2
    • NotebookLM summary: Key technical themes include the transition from brittle regex-based parsing to tree-sitter AST integration for accurate function detection and the implementation of advanced features like static call graph analysis to identify “callers” and “callees.” The dialogue tracks a rigorous debugging process where the developers solve real-world scaling issues, such as Python recursion limits in deep directory structures and encoding errors in large file-list processing. Ultimately, the text serves as a technical log of the tool’s evolution into a robust system capable of handling hundreds of thousands of files while offering high-level insights like function frequency ranking and semantic cross-referencing.
    • Tree-Sitter Parsing Integration: To fix issues where regex parsing missed nested structures and C++ class methods, the team implemented an iterative Tree-Sitter AST traversal, which drastically improved method detection without hitting recursion limits.
    • Call Graph Navigation: Capitalizing on the high-speed inverted index, the team built call graph features like –callers (to see where a function is invoked) and –most-called (to rank functions by usage frequency). This provided instant visibility into code connectivity and external library usage.
    • Strategic Discovery Metrics: To help analysts quickly answer “What matters here?”, the system introduced composite scoring algorithms. This led to the creation of –hotspots (ranking by call count × log2 of lines), –entry-points (identifying large but uncalled [or rarely-called] functions like API implementations or event handlers), and –domain-fns (penalizing generic names to surface unique business logic).
    • Multi-Tier Deduplication: Realizing that metric scores were heavily distorted by copy-pasted files and decompilation artifacts, a three-tier deduplication system was architected. The tool now deduplicates at the file level (SHA1), exact function level, and structural level (“funcstrings” that strip comments and names), successfully consolidating tens of thousands of clones that had the “same tune, different words”.
    • Class-Level Analysis: The system’s structural awareness was expanded to support Class structures via commands like –list-classes and –class-hotspots. This included cross-file method association, successfully linking C++ class declarations in .h headers to their implementations in .cpp files.
    • Regression Testing and Refactoring: To ensure stability during this rapid development, a comprehensive regression test harness (test_code_search.py) was introduced.
    • Furthermore, a massive refactoring of the tool’s main() function was executed, extracting 28 separate command handlers to establish parity between the CLI and interactive modes and lay the groundwork for a future GUI.
  • Code exam, part 1b
    • NotebookLM summary: An iterative collaboration between a developer and an AI to refine an air-gapped source code examination tool designed for patent litigation. The project centers on the multisect search functionality, which enables experts to find code intersections matching complex patent claim elements through a dual-tier strategy of tight literal matches and broad implementation-level synonyms. To handle massive codebases like Android or LLVM, the system utilizes a two-phase optimization that scans an inverted index for file survivors before performing expensive function-level lookups. Key architectural enhancements include IDF-weighted scoring to prioritize rare, discriminating technical terms and scope deduplication to filter out redundant results across the folder, file, and function hierarchy. The source also details a claim-search feature that integrates an LLM to translate abstract legal language into searchable code patterns while maintaining security via external network warnings and support for local model endpoints. Finally, the text explores the potential for indexing demangled C++ signatures from disassembly files to bridge the gap between patent claims and proprietary commercial binaries.
    • Implementation of the Two-Phase “Funnel” Search: To resolve a bottleneck, Claude architected a two-phase optimization strategy. Phase 1 instantly intersects file sets via the inverted index to find a small pool of “survivor” files, and Phase 2 performs detailed regex and function boundary lookups (using a faster bisect method) only on those survivors. This reduced search times from 60+ minutes to under 2 minutes.
    • Real-World Patent Stress Testing: With performance restored, the user and Claude tested the tool against several real-world patents (transformers, facade servers). The tests validated that the BROAD search tier successfully bridged the vocabulary gap between legal language and developer implementation, provided the patent claim contained strongly discriminating terms.
    • Disassembled Binary Indexing: The session concluded with the user introducing a novel idea to index disassembled commercial binaries (.a or .asm files). Claude validated that extracting demangled C++ signatures from these disassemblies would create a highly structured “vocabulary bridge,” allowing the tool to map patent claims to closed-source software without needing the original source code.
  • Offline code analysis with local LLM and RAG” (first session)
    • Me: “I need a tool to analyze source code in an environment with absolutely no internet connection. (This is for confidential source-code examination in litigation.) The analysis would include an AI chatbot that could answer questions about the code. So there must be a local LLM + local RAG. There cannot be any risk that the LLM will train on the proprietary code, so this tool would be loaded onto a machine and installed, and then all internet turned off. The RAG would allow loading of large trees of code written in C/C++, Java, JavaScript, Python, etc., and would also allow loading of text docs (such as patent PDFs) against which the code could be compared. In an initial version, there would not be specialized parsing for different programming languages, but that would likely be requested in a revision.”
    • As immediate response, Claude architected comprehensive air-gapped code analysis system with local LLM and RAG: “I can help you design an air-gapped code analysis system for legal discovery. This is a well-defined use case with clear security requirements. Here’s a comprehensive architecture…” [later replaced RAG with inverted index based on my index/find tool]
    • Addressing AI Confusion and Data Persistence: The user discovered that the LLM was confusing its own role (legal discovery) with the purpose of the code it was analyzing, requiring prompt engineering fixes. They also caught a critical bug where ChromaDB persisted data across runs, inadvertently mixing thousands of PyTorch files with the DeepSeek codebase.
    • Architectural Pivot to Fast Structural Parsing: Realizing that calling the LLM for every single function was unscalably slow (potentially taking up to 80 hours for 10,000 functions) and prone to “context bleeding,” they pivoted to a new architecture (code_analyzer_v3.py). This approach used Tree-sitter for lightning-fast, non-AI structural extraction, reserving the LLM for selective, user-driven deep dives.
    • Discovering the Need for Adversarial Masking: During testing, the user noted that the AI was being “lazy” by relying on function names rather than reading the actual code logic (e.g., guessing standard values for clip_gradient instead of reading the code’s specific constants).
    • Testing with deliberately misnamed functions proved the AI got confused, leading to the creation of a name-masking feature (–mask-names / –mask-all) to force true logic analysis.
    • Success in Blind Algorithm Recognition: The session concluded with targeted tests demonstrating that, even with function and variable names completely masked, the local LLM could successfully identify algorithms and patterns (such as QuickSort, DJB2 Hash, Euclidean GCD, and buffer overflow vulnerabilities) purely from their structural “fingerprints”.

AI chatbot front-end to this web site built with Google NotebookLM (NBLM):

AI “Chatbook” (using Google NotebookLM) for Patent Litigation book by Andrew Schulman

PatClaim.ai (forthcoming; some areas being implemented and/or investigated include):

PatLitig.ai (forthcoming; some areas being implemented and/or investigated include):

RE/AI: Reverse engineering, Source code examination, and AI:

  • See ai-reverse-engineering-source-code-examination/
  • Two major topics here:
    • Reverse engineering/source code examination, using AI-based tools,
    • Changes to standard reverse engineering and source-code examination methodologies, when examining AI-based software
  • The name RevEng.ai is already taken (“Reverse Engineering meets Artificial Intelligence / AI powered Binary Analysis platform for Reverse Engineering and Malware Analysis”)

Services: source code examination & software reverse engineering

For contact information, see About Us or send email.

Somewhat-recent CV available here; a confidential list of past cases and clients is available under a non-disclosure agreement.

Sample source-code examination and reverse engineering cases and projects here.

LinkedIn profile here

Partial collection at academia.edu of drafts and (mostly older) articles