The Cartography of Code: How an AI Subagent Systematically Mapped the PCE Extraction Landscape
Introduction
In the course of a complex engineering session involving the CuZK GPU-accelerated proving engine for Filecoin, an AI assistant faced a challenge that would be familiar to any developer working on a large, unfamiliar codebase: it needed to understand how a critical optimization — the Pre-Compiled Constraint Evaluator (PCE) — was built, cached, named, and deployed across four distinct proof types. The assistant had already implemented PCE extraction for WinningPoSt, WindowPoSt, and SnapDeals in the parent session, extending the existing PoRep-only support. But a crash had occurred when testing WindowPoSt with PCE enabled, revealing a subtle mismatch between constraint systems. To debug this, the assistant needed a complete map of the PCE subsystem — its CLI commands, its file naming conventions, its cache architecture, and its extraction pathways.
What followed was a masterclass in systematic codebase exploration. The assistant spawned a subagent with a single, focused task: "Find PCE build details per proof type." Over the course of six messages, the subagent executed a methodical investigation that progressed from reconnaissance to deep reading to targeted hypothesis testing, culminating in a comprehensive technical reference document. This article examines that entire sub-session as a unified case study in AI-assisted software archaeology — revealing the strategies, assumptions, and reasoning patterns that enabled the assistant to transform scattered source code into actionable knowledge.
The Mission: A Research-Driven Subagent Request
The subagent session began with a meticulously structured user message ([msg 0]). The user — the AI assistant from the parent session — issued a request that was both broad and precise: find detailed information about how to build and generate PCE for all 32G proof types, covering PoRep C2, WinningPoSt, WindowPoSt, and SnapDeals. The request enumerated eight specific investigative tasks, each targeting a particular file or search pattern:
- Read the bench tool's
main.rsfor PCE-related subcommands and CLI flags - Read the pipeline module for PCE cache statics, preload functions, and extraction logic
- Read the disk persistence module for file naming conventions
- Read the user-facing documentation for PCE generation instructions
- Read the daemon binary for CLI flags related to PCE
- Read the example configuration and config files for PCE-related options
- Search for "pce" references in CLI argument definitions
- Map each proof type to its PCE file name and extraction function This was not a casual inquiry. The user wanted "exact commands and steps a user would follow to generate PCE for all 32G proof types." They were asking for a complete operational guide, and they expected the subagent to assemble it from source code, documentation, and configuration files scattered across the repository. The structure of this request reveals several deliberate decisions. First, the user prioritized source code over documentation — the first three tasks pointed directly to Rust source files, while documentation and configuration came later. This reflects an understanding that in an actively developed codebase, the source code is the most reliable source of truth. Second, the tasks were ordered to trace the PCE flow from the user-facing CLI, through the core caching layer, down to the serialization layer — a classic top-down decomposition. Third, the request included both targeted reads (specific files) and broad searches (grep patterns), ensuring comprehensive coverage. The articles in this series have analyzed each individual message in depth. Article [1] examines the opening request as a masterclass in research delegation, noting how the user decomposed a complex debugging problem into well-scoped exploration tasks. Article [3] analyzes the assistant's first response — a glob-based reconnaissance operation — and reveals how the assistant validated file paths before committing to reads. Article [5] examines the parallel read strategy that followed, where the assistant read seven key files simultaneously to build a surface-level understanding. Article [4] analyzes the information-gathering phase where the assistant read deeper into the pipeline module and performed a broad grep. Article [6] examines the pivotal moment when a targeted grep revealed that non-PoRep proof types lack dedicated extraction functions. And Article [2] analyzes the final synthesis — a comprehensive reference document that transformed scattered code fragments into actionable knowledge. This article synthesizes these individual analyses into a unified narrative, tracing the subagent's journey from initial reconnaissance to final synthesis, and extracting the broader lessons for AI-assisted software exploration.## Phase I: Reconnaissance — The Glob-First Strategy The subagent's first response ([msg 1]) was not to immediately read the files the user specified, but to pause and survey the terrain. The assistant issued three parallel glob commands: one for all Rust source files under
extern/cuzk/, one for all TOML configuration files, and one for documentation files matchingcuzk*.md. This seemingly simple opening move embodied a sophisticated understanding of how to approach unfamiliar codebases efficiently. The glob results revealed the full set of Rust source files organized by crate:cuzk-proto,cuzk-daemon,cuzk-pce,cuzk-server,cuzk-bench, andcuzk-core. Crucially, the glob also discovered files the user had not mentioned — such ascuzk-pce/src/recording_cs.rs,cuzk-pce/src/eval.rs,cuzk-pce/src/density.rs, andcuzk-pce/src/csr.rs— which were part of the PCE subsystem but absent from the user's eight tasks. By discovering these, the assistant gained a more complete picture of the codebase than the user's instructions alone would provide. The glob-first approach embodies a fundamental principle of software exploration: validate your assumptions before acting on them. The assistant did not trust that the user's file paths were correct; it verified them independently. This was especially important in a subagent context where the parent session might have made changes to the repository that the subagent could not see directly. The output of this message was a validated file inventory — a map of the territory that the assistant would use to plan its next moves.
Phase II: Deep Reading — Parallel File Acquisition
With the file inventory in hand, the assistant proceeded to Phase II ([msg 2]): reading the actual contents of the key files. The assistant selected seven files to read simultaneously, each serving a distinct purpose in the PCE knowledge puzzle:
cuzk-bench/src/main.rs: The CLI entry point, containing subcommand definitions and proof type string mappingscuzk-core/src/pipeline.rs: The heart of the pipelined proving engine, containing PCE cache statics, preload functions, and extraction logiccuzk-pce/src/disk.rs: The PCE disk persistence layer, defining the binary file format and naming conventionsdocumentation/en/experimental-features/cuzk-proving-daemon.md: User-facing documentationcuzk-daemon/src/main.rs: The daemon binary entry point, showing startup and initializationcuzk.example.toml: The example configuration filecuzk-core/src/config.rs: The configuration struct definitions The selection was methodical: the assistant covered CLI (bench), core logic (pipeline), persistence (disk), documentation, daemon startup, configuration example, and configuration schema. This was a comprehensive coverage of the PCE knowledge domain. However, the read tool returned only the beginning of each file. For large files likepipeline.rs(which is over 1400 lines), the assistant saw only the module-level documentation and the first few lines of implementation. The critical PCE cache statics, extraction functions, and synthesis logic were deeper in the file, still hidden. The assistant recognized this gap and planned subsequent reads to fill it.
Phase III: Filling the Gaps — Deeper Reads and Broad Search
In Phase III ([msg 3]), the assistant continued its investigation by reading deeper into pipeline.rs (starting at line 1369), reading additional files that the initial batch had missed (cuzk-pce/src/lib.rs, cuzk-core/src/engine.rs, cuzk-core/src/srs_manager.rs), and performing a broad grep for all PCE-related identifiers.
The read of cuzk-pce/src/lib.rs was particularly significant. This file was not in the user's explicit list, but the assistant recognized it as essential. It contained the conceptual foundation of the entire PCE system — explaining that PoRep circuits have a fixed R1CS structure where constraint matrices are identical across proofs, and that PCE eliminates the redundancy of rebuilding ~130M LinearCombination objects per partition per proof. By reading this file, the assistant gained the "why" behind the "how."
The broad grep for pce|PCE|preload_pce|pce_filename|extract_and_cache_pce returned 263 matches across the codebase, giving the assistant a bird's-eye view of every file that touches PCE functionality. This was a classic exploration strategy: first get the lay of the land, then dive into specific files. The grep results would guide subsequent reads, pointing the assistant to files it hadn't considered.
Phase IV: The Pivotal Discovery — Asymmetric Extraction Support
Phase IV ([msg 4]) was the turning point of the entire investigation. The assistant had accumulated substantial knowledge about the PCE infrastructure: it had seen the four static OnceLock caches, the preload_pce_from_disk() function that iterates over all four circuit types, and the extract_and_cache_pce() generic extraction function. It had also seen the PoRep-specific extract_and_cache_pce_from_c1() function in the bench tool.
But a crucial question remained: Do WinningPoSt, WindowPoSt, and SnapDeals have their own dedicated extraction functions? The assistant explicitly stated its intent: "Now let me search for the PCE extraction logic for non-PoRep proof types to understand if there are specific extraction functions."
The grep command used a carefully crafted regular expression combining two patterns: extract.*pce.*(post|snap|winning|window) and pce.*extract.*(post|snap|winning|window). This covered both naming conventions — whether the function was named extract_pce_for_window_post or window_post_pce_extract. The result was unequivocal: "No files found."
This negative result was the most important finding of the entire sub-session. It revealed a fundamental asymmetry in the CuZK codebase: only PoRep has a dedicated, user-invokable PCE extraction pathway. For the other three proof types — WinningPoSt, WindowPoSt, and SnapDeals — PCE extraction is entirely implicit, happening as a side effect of the first proof submission through the daemon's synthesize_auto() function.
This finding had immediate implications for the parent session's debugging effort. The WindowPoSt crash that had motivated the investigation could not be attributed to a missing extraction function — the extraction pathway existed, but it was automatic rather than explicit. The bug lay elsewhere, in the structural mismatch between RecordingCS and WitnessCS that the parent session would later fix.
Phase V: Synthesis — The Comprehensive Reference
With all the pieces in place, the assistant produced its final synthesis ([msg 5]): a comprehensive technical reference document spanning eleven sections. The document was organized into a logical flow that moved from concept to action:
- What PCE Is — A primer establishing the "why" before the "how"
- PCE File Naming Convention — The mapping from circuit IDs to disk filenames, presented as a table
- PCE In-Memory Cache Statics — The
OnceLockvariables and lookup routing - PCE Preloading at Daemon Startup — How
preload_pce_from_disk()works - PCE Extraction and Caching — The
extract_and_cache_pce()function and the automatic extraction path - PCE File Format — Binary format details
- How to Generate PCE for All 32G Proof Types — The practical workflow, split into automatic and explicit methods
- Proof Type String Mappings — How CLI strings map to internal enum values
- Environment Variables —
CUZK_DISABLE_PCEandFIL_PROOFS_PARAMETER_CACHE - Configuration Options — The TOML config surface area
- Summary Workflow — A step-by-step deployment guide The document was remarkable not just for its completeness, but for its editorial choices. The assistant prioritized the automatic workflow (Method A) over the explicit bench tool method (Method B), reflecting a strong recommendation that in production, users should simply start the daemon and let it handle PCE extraction. The assistant highlighted negative findings explicitly — noting that no standalone extraction tool exists for non-PoRep types — preventing future engineers from searching for something that doesn't exist. And the assistant used tables for scannability, making it easy for an engineer to find, say, the WindowPoSt PCE filename in seconds.
The Debugging Payoff: Connecting the Map to the Bug
The comprehensive PCE reference was not an end in itself. It was a tool for debugging the WindowPoSt crash that had motivated the entire investigation. The crash manifested as a mismatch in input counts: the witness had 26,036 inputs while the PCE expected 25,840 — a difference of exactly 196 inputs.
Armed with the PCE map, the assistant could trace the root cause. The FallbackPoSt circuit dispatches to different synthesis paths based on the is_extensible() flag on the constraint system. RecordingCS (used for PCE extraction) returned false by default, routing the circuit through synthesize_default. WitnessCS (used for fast proving) returned true, routing it through synthesize_extendable, which splits work into parallel chunks, each allocating a "temp ONE" input. With 196 synthesis CPUs configured, this produced exactly 196 extra inputs — matching the discrepancy.
The fix involved making RecordingCS fully extensible by implementing is_extensible() and extend() methods, and correcting its initialization to pre-allocate a ONE input. This ensured structural parity between the extraction and proving paths, restoring correct proving for WindowPoSt with PCE enabled.
Broader Lessons: The Art of Systematic Codebase Exploration
The subagent's investigation offers several lessons for AI-assisted software exploration:
1. Start with reconnaissance, not deep reading. The glob-first strategy validated assumptions and discovered unexpected files before any code was read. This upfront investment saved time by ensuring subsequent reads targeted the right files.
2. Use targeted grep to test hypotheses. The assistant could have traced through each proof type's synthesis path manually. Instead, it used a pattern-based search that quickly revealed whether dedicated extraction functions existed. This was more efficient and carried only a small risk of false negatives.
3. Negative results are valuable findings. The "No files found" grep result was the most important discovery of the session. It revealed an asymmetry that would have been invisible to anyone who assumed symmetric support across proof types.
4. Synthesize, don't just dump. The final document was not a list of file contents or grep output. It was a reorganized, curated reference that connected dots across files — showing how circuit_id_pce_name() feeds into pce_filename(), which feeds into pce_disk_path(), which is called by preload_pce_from_disk(), which is invoked at daemon startup. This cross-cutting synthesis is where AI assistants provide the most value.
5. Understand the "why" behind the "how." The assistant read cuzk-pce/src/lib.rs even though the user hadn't asked for it, recognizing that understanding the purpose of PCE was necessary to explain its usage. This inference of unstated needs is a hallmark of effective technical communication.
Conclusion
The subagent session that mapped the PCE extraction landscape is a case study in how AI-assisted software exploration should work. It began with a precise research request, proceeded through systematic phases of reconnaissance, deep reading, and hypothesis testing, and culminated in a comprehensive reference that not only answered the user's explicit questions but also revealed a critical asymmetry in the codebase. That asymmetry — the lack of dedicated extraction functions for non-PoRep proof types — was not a bug in itself, but it was a crucial piece of context for understanding the WindowPoSt crash that the parent session was debugging.
The investigation demonstrates that the highest value of an AI assistant in software engineering is not in retrieving information but in transforming it — connecting scattered facts across files, identifying patterns and gaps, and presenting the results in a form that drives action. The PCE map that emerged from this subagent session was not just a reference document; it was a diagnostic tool that enabled the assistant to trace the root cause of a crash, implement a fix, and restore correct proving for WindowPoSt with PCE enabled.
In the end, the cartography of code is not about listing files and functions. It is about understanding how pieces connect, where assumptions break down, and what knowledge is needed to make the next engineering decision. The subagent's journey from glob patterns to a comprehensive reference document is a blueprint for how to explore any unfamiliar codebase — systematically, hypothesis-driven, and with an eye for the gaps that matter.## References
[1] "Mapping the PCE Landscape: A Deep Dive Into a Research-Driven Subagent Request" — Analysis of message index 0, the user's opening research request.
[2] "The Architecture of Knowledge: How an AI Assistant Compiled a Definitive Reference for Pre-Compiled Constraint Evaluation" — Analysis of message index 5, the final synthesis document.
[3] "The Art of Discovery: How a Subagent Mapped the PCE Landscape Before Reading a Single Line of Code" — Analysis of message index 1, the glob-based reconnaissance phase.
[4] "The Information-Gathering Phase: How an AI Assistant Systematically Explores a Complex Codebase" — Analysis of message index 3, the deeper reads and broad grep phase.
[5] "Gathering the Blueprints: How an AI Assistant Systematically Reads Source Code to Map PCE Extraction Across Proof Types" — Analysis of message index 2, the parallel file read phase.
[6] "The Search That Changed Everything: Discovering Asymmetric PCE Extraction Support in CuZK" — Analysis of message index 4, the pivotal negative grep result.