Layer 1 skill for source code analysis — decompose any codebase into analyzable units, extract behavioral claims with provenance. Supports three target shapes (source tree, bundle, decompiled binary), with per-language grep patterns and analysis templates.
Installs into .claude/skills of the current project.
Are you the author of Source Analysis?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/prime-radiant-inc-source-analysis)
---
name: source-analysis
description: Layer 1 skill for source code analysis — decompose any codebase into analyzable units, extract behavioral claims with provenance. Supports three target shapes (source tree, bundle, decompiled binary), with per-language grep patterns and analysis templates.
---
# Source Analysis Methodology
Extract behavioral intelligence from source code. Decompose the codebase into analyzable units, then systematically analyze each unit for behavioral claims with full provenance.
## When to Use This Mode
Source analysis activates when:
- The discovery inventory identifies source code files at the target path
- Any source code needs behavioral analysis (any language, bundled or not)
- Decompiled output exists at `workspace/raw/source/decompiled/`
## General Approach
Source analysis takes three shapes depending on what the target looks like:
- **Source tree** — a repository with a package manifest and conventional directory layout (Python, Rust, Go, Swift, Java, Node/TS, C++, etc.). Follow the **Source Tree Pipeline** below.
- **Bundle** — a single-file minified or packed artifact (JavaScript bundle, Electron asar, webpack/esbuild output). Follow the **Bundle Pipeline** below.
- **Decompiled binary** — a compiled artifact where source isn't directly available. Decompile first via the **Decompilation Path**, then analyze the decompiled output using whichever of the above shapes fits.
Regardless of shape, the pipeline follows the same logical steps:
1. **Assess the source.** What language? How is it organized? How large is it?
2. **Decompose into analyzable units.** Use the language's natural boundaries (modules, packages, files) when they exist. Split bundled artifacts into chunks when they don't.
3. **Analyze each unit exhaustively.** Read every line. Identify every function, method, class. Understand what each does behaviorally.
4. **Extract behavioral specifications.** Write what the code DOES (observable behavior), not how it's structured (implementation details). Every claim gets a provenance citation.
Phases 6-8 (per-unit analysis, per-function deep analysis, targeted extraction) are shape-agnostic and apply to all three paths.
## Decompilation Path
When source code isn't directly available, decompile binaries into structured source before analysis.
### Language-Specific Decompilation Tools
| Language/Platform | Tools | Notes |
|-------------------|-------|-------|
| JVM (Java, Kotlin) | cfr, procyon, fernflower | cfr is standalone JAR; fernflower is IntelliJ's built-in decompiler |
| .NET (C#, F#) | ilspy, dotPeek CLI | ilspy has a command-line mode suitable for automation |
| Python (.pyc, .pyo) | uncompyle6, decompyle3 | decompyle3 targets Python 3.7+; uncompyle6 covers older versions |
| JavaScript (bundled/obfuscated) | js-beautify | Also covered by the Bundle Pipeline below |
| Native (x86, ARM, etc.) | ghidra headless, radare2 | Produces pseudocode, not true source; useful for behavioral extraction but lower fidelity |
### Process
1. **Identify binary type.** Determine the platform and format (JAR, DLL, .pyc, ELF, Mach-O, etc.).
2. **Check tool availability.** Verify the appropriate decompiler is installed and accessible. If tools are unavailable, warn and fall back to binary analysis (strings, symbols, imports/exports).
3. **Decompile to workspace.** Output decompiled source to `workspace/raw/source/decompiled/`. Preserve directory structure from the binary where possible (e.g., Java package paths).
4. **Treat decompiled output as structured source.** Once decompiled, analyze using the same General Approach above — each decompiled file is an analyzable unit.
```bash
mkdir -p workspace/raw/source/decompiled
# Example: JVM with cfr
java -jar cfr.jar target.jar --outputdir workspace/raw/source/decompiled/
# Example: Python with uncompyle6
uncompyle6 -o workspace/raw/source/decompiled/ target.pyc
# Example: .NET with ilspy
ilspycmd target.dll -o workspace/raw/source/decompiled/
# Example: Native with Ghidra headless
analyzeHeadless /tmp/ghidra_project proj -import target.bin -postScript ExportDecompiled.java workspace/raw/source/decompiled/
```
### Quality Notes
Decompiled code differs from original source in predictable ways:
- **Variable and parameter names are lost.** Decompilers generate synthetic names (e.g., `var1`, `a0`). Focus on behavioral patterns, not identifier semantics.
- **Comments are lost.** All inline documentation is gone. Rely on string constants, API calls, and control flow for behavioral understanding.
- **Control flow may be less readable.** Optimized bytecode can decompile into awkward `goto`-style structures or deeply nested conditionals.
These limitations are acceptable for behavioral extraction. The goal is to understand what the code does, not to recover the original source.
## Source Tree Pipeline
Source tree analysis is the common path for Python, Rust, Go, Swift, Java, C++, and similar languages that ship as a repository rather than a single compiled artifact. The target is a directory with a package manifest and a conventional source layout.
The Source Tree Pipeline defines Phases ST1-ST3 (survey, enumeration, and unit preparation). After ST3, control flows into the shape-neutral Phases 6-8 shared with the Bundle Pipeline.
```dot
digraph source_tree_analysis {
rankdir=TB;
"Start (source tree)" [shape=doublecircle];
"Phase ST1: Manifest discovery" [shape=box];
"Phase ST2: Module enumeration" [shape=box];
"Phase ST3: Prepare for per-unit analysis" [shape=box];
"→ Phase 6 (shape-neutral)" [shape=box, style=filled, fillcolor="#f0f0f0"];
"Start (source tree)" -> "Phase ST1: Manifest discovery";
"Phase ST1: Manifest discovery" -> "Phase ST2: Module enumeration";
"Phase ST2: Module enumeration" -> "Phase ST3: Prepare for per-unit analysis";
"Phase ST3: Prepare for per-unit analysis" -> "→ Phase 6 (shape-neutral)";
}
```
### Phase ST1: Manifest Discovery
Identify the package manifest and read it. The manifest names the package, declares dependencies, and lists the source roots.
| Language | Manifest | Source roots |
|----------|----------|--------------|
| Python | `pyproject.toml`, `setup.py`, `setup.cfg` | `src/`, `<package>/`, or top-level modules |
| Rust | `Cargo.toml` (+ workspace `Cargo.toml`) | `src/`, each crate's `src/` |
| Go | `go.mod` | Module root and every directory with `.go` files |
| Swift | `Package.swift`, `*.xcodeproj/project.pbxproj` | `Sources/<target>/` per target |
| Java/Kotlin | `pom.xml`, `build.gradle`, `build.gradle.kts` | `src/main/java/`, `src/main/kotlin/` |
| C#/F# | `*.csproj`, `*.fsproj` | project-relative source directories |
| C/C++ | `CMakeLists.txt`, `Makefile`, `meson.build` | varies; often `src/` and `include/` |
| Node (non-bundled) | `package.json` | `src/`, `lib/`, `index.js` |
Write the survey to `workspace/raw/source/analysis/survey.md`:
```markdown
# Source Tree Survey
**Language:** <primary>
**Manifest:** <path>
**Package name:** <from manifest>
**Source roots:** <list>
**Dependency count:** <count>
**Line count by language:** <table>
```
### Phase ST2: Module Enumeration
Walk the source roots and produce a module list. A "module" in this pipeline is whatever the language's natural unit of organization is — a Python package, a Rust module/crate, a Go package, a Swift target, a Java package. Don't invent your own boundaries; use the language's.
```bash
# Python: every directory with __init__.py plus every top-level .py file
find <source-root> -name '__init__.py' -exec dirname {} \;
find <source-root> -maxdepth 1 -name '*.py' -not -name '__init__.py'
# Rust: every directory with a mod.rs or every file in src/
find <crate>/src -name '*.rs'
# Go: every directory with at least one .go file
find <source-root> -name '*.go' -exec dirname {} \; | sort -u
# Swift: every directory under Sources/
find Sources -mindepth 2 -maxdepth 2 -type d
# Java/Kotlin: every directory with .java or .kt files
find src/main -name '*.java' -o -name '*.kt' -exec dirname {} \; | sort -u
```
Write the module inventory to `workspace/raw/source/manifests/module-manifest.json`:
```json
{
"modules": [
{"path": "src/parser", "files": 7, "lines": 1240, "language": "rust"},
{"path": "src/http", "files": 4, "lines": 680, "language": "rust"}
]
}
```
### Phase ST3: Prepare for Per-Unit Analysis
Once Phases ST1-ST2 have produced the survey and module manifest, each module is ready to be treated as the analyzable unit for the shape-neutral Phase 6. The analysis unit differs by target shape: in a bundle, the unit is a chunk from the bundle-splitter; in a source tree, it's a module as the language defines it. Both produce the same per-unit output format.
Phases 6-8 (Per-Unit Analysis, Per-Function Deep Analysis, Targeted Extraction), described later in this skill, apply from here on.
---
## Bundle Pipeline
The Bundle Pipeline defines Phases B1-B5 (bundle-specific decomposition). After B5, control flows into the shape-neutral Phases 6-8 shared with the Source Tree Pipeline.
```dot
digraph bundle_pipeline {
rankdir=TB;
"Start (bundle target)" [shape=doublecircle];
"Phase B1: Beautify bundle" [shape=box];
"Phase B2: Find module boundaries" [shape=box];
"Phase B3: Extract chunks" [shape=box];
"Phase B4: Extract functions" [shape=box];
"Phase B5: Extract strings" [shape=box];
"→ Phase 6 (shape-neutral)" [shape=box, style=filled, fillcolor="#f0f0f0"];
"Start (bundle target)" -> "Phase B1: Beautify bundle";
"Phase B1: Beautify bundle" -> "Phase B2: Find module boundaries";
"Phase B2: Find module boundaries" -> "Phase B3: Extract chunks";
"Phase B3: Extract chunks" -> "Phase B4: Extract functions";
"Phase B4: Extract functions" -> "Phase B5: Extract strings";
"Phase B5: Extract strings" -> "→ Phase 6 (shape-neutral)";
}
```
Phases B1-B5 are bundle decomposition infrastructure (bundle-splitter). Phases 6-7 produce behavioral analysis (chunk-analyzer, function-analyzer) and are shape-neutral. Phase 8 is optional targeted extraction (targeted-extractor).
For non-bundled targets, run the Source Tree Pipeline's Phases ST1-ST3 instead of this section's B1-B5, then flow into the same shape-neutral Phases 6-8.
## Phase B1: Bundle Preparation
### 1.1 Beautify if Needed
Check if the bundle is minified by comparing line count to byte count. A file with few lines but many bytes is minified.
```bash
LINE_COUNT=$(wc -l < "$BUNDLE")
BYTE_COUNT=$(wc -c < "$BUNDLE")
if [ "$LINE_COUNT" -lt 100 ] && [ "$BYTE_COUNT" -gt 100000 ]; then
echo "Minified - needs beautification"
mkdir -p workspace/raw/source
BEAUTIFIED="workspace/raw/source/target.js"
if [ ! -f "$BEAUTIFIED" ]; then
npx js-beautify --type js -f "$BUNDLE" -o "$BEAUTIFIED"
fi
TARGET="$BEAUTIFIED"
else
TARGET="$BUNDLE"
fi
```
Always check for an existing beautified version before re-beautifying. Multiple agents may operate on the same bundle.
### 1.2 Initial Survey
```bash
# Size and line count
ls -lh "$TARGET"
wc -l "$TARGET"
# Detect bundler type
head -100 "$TARGET" > workspace/raw/source/analysis/bundle-header.txt
grep -m1 "webpack\|esbuild\|rollup\|parcel" "$TARGET" || echo "Unknown bundler"
```
Write the survey to `workspace/raw/source/analysis/survey.md`.
## Phase B2: Find Module Boundaries
### 2.1 Bundler-Specific Markers
#### Webpack
```bash
# Module ID markers
grep -n "^/\*\*\*\*\*\*/ \"" "$TARGET" > manifests/webpack-modules.txt
# Export declarations
grep -n "__webpack_require__\.d\|__webpack_exports__" "$TARGET" | head -100 > manifests/webpack-exports.txt
```
#### esbuild
```bash
# esbuild source comments
grep -n "^// " "$TARGET" | grep -v "^// $" > manifests/esbuild-markers.txt
```
#### Generic IIFE Boundaries
```bash
# Function expression boundaries
grep -n "^(function\|^!function\|^var [a-z]* = function" "$TARGET" > manifests/iife-boundaries.txt
```
### 2.2 Heuristic Boundaries
When no bundler-specific markers are found, fall back to heuristics:
```bash
# Long comment separators
grep -n "^/\*\*\*\*\*\*\*\*" "$TARGET" > manifests/separator-comments.txt
# Export clusters
grep -n "^exports\.\|^module\.exports" "$TARGET" > manifests/export-points.txt
# Large gaps (blank lines often separate modules)
awk 'NF==0 {if(++blank>=3) print NR": --- blank section ---"} NF>0 {blank=0}' "$TARGET" | head -100
```
## Phase B3: Extract Chunks
### 3.1 Split by Module Markers
```bash
mkdir -p workspace/raw/source/chunks
# Webpack-style split
csplit -f workspace/raw/source/chunks/chunk- -n 4 "$TARGET" '/^\/\*\*\*\*\*\*\//' '{*}' 2>/dev/null
# Fall back to line-count splitting if no clear markers
if [ $(ls workspace/raw/source/chunks/ | wc -l) -lt 5 ]; then
rm workspace/raw/source/chunks/*
split -l 2000 "$TARGET" workspace/raw/source/chunks/chunk-
fi
# Rename to .js
for f in workspace/raw/source/chunks/chunk-*; do
[ "${f%.js}" = "$f" ] && mv "$f" "${f}.js"
done
```
### 3.2 Generate Chunk Manifest
```bash
echo '{"chunks": [' > workspace/raw/source/manifests/chunk-manifest.json
for chunk in workspace/raw/source/chunks/*.js; do
name=$(basename "$chunk")
lines=$(wc -l < "$chunk")
size=$(wc -c < "$chunk")
# Extract first meaningful identifier
first_func=$(grep -oP "function [a-zA-Z_][a-zA-Z0-9_]*" "$chunk" | head -1)
first_class=$(grep -oP "class [a-zA-Z_][a-zA-Z0-9_]*" "$chunk" | head -1)
echo " {\"file\": \"$name\", \"lines\": $lines, \"bytes\": $size, \"first_func\": \"$first_func\", \"first_class\": \"$first_class\"},"
done >> workspace/raw/source/manifests/chunk-manifest.json
echo ']}' >> workspace/raw/source/manifests/chunk-manifest.json
```
## Phase B4: Extract Functions
### 4.1 Find Function Definitions
```bash
mkdir -p workspace/raw/source/functions
# Named functions
grep -n "function [a-zA-Z_][a-zA-Z0-9_]*\s*(" "$TARGET" > workspace/raw/source/manifests/function-locations.txt
# Arrow function assignments
grep -n "const [a-zA-Z_][a-zA-Z0-9_]* = (" "$TARGET" >> workspace/raw/source/manifests/function-locations.txt
grep -n "const [a-zA-Z_][a-zA-Z0-9_]* = async" "$TARGET" >> workspace/raw/source/manifests/function-locations.txt
```
### 4.2 Extract Individual Functions
Extract each significant function (more than 10 lines) to its own file:
```bash
cat > /tmp/extract_funcs.js << 'EOF'
const fs = require('fs');
const code = fs.readFileSync(process.argv[2], 'utf8');
const funcPattern = /function\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\([^)]*\)\s*\{/g;
let match;
let funcId = 0;
const outDir = process.argv[3] || 'workspace/raw/source/functions';
while ((match = funcPattern.exec(code)) !== null) {
const name = match[1];
const start = match.index;
let depth = 1;
let i = code.indexOf('{', start) + 1;
while (depth > 0 && i < code.length) {
if (code[i] === '{') depth++;
if (code[i] === '}') depth--;
i++;
}
const funcCode = code.slice(start, i);
if (funcCode.split('\n').length > 10) {
fs.writeFileSync(
`${outDir}/func-${String(funcId++).padStart(4, '0')}-${name}.js`,
funcCode
);
}
}
EOF
node /tmp/extract_funcs.js "$TARGET" workspace/raw/source/functions
```
### 4.3 Generate Function Manifest
```bash
echo '{"functions": [' > workspace/raw/source/manifests/function-manifest.json
for func in workspace/raw/source/functions/*.js; do
name=$(basename "$func" .js)
lines=$(wc -l < "$func")
params=$(grep -oP "function[^(]*\([^)]*\)" "$func" | head -1)
echo " {\"file\": \"$name\", \"lines\": $lines, \"signature\": \"$params\"},"
done >> workspace/raw/source/manifests/function-manifest.json
echo ']}' >> workspace/raw/source/manifests/function-manifest.json
```
## Phase B5: String Extraction
### 5.1 Catalog All Strings
```bash
mkdir -p workspace/raw/source/manifests
# Extract all strings with line numbers (minimum 5 chars)
grep -noP '"[^"]{5,}"' "$TARGET" > workspace/raw/source/manifests/strings-raw.txt
# Categorize
grep -P '"https?://' workspace/raw/source/manifests/strings-raw.txt > workspace/raw/source/manifests/strings-urls.txt
grep -P '"[A-Z][A-Z_]{3,}"' workspace/raw/source/manifests/strings-raw.txt > workspace/raw/source/manifests/strings-constants.txt
grep -P '"--[a-z]' workspace/raw/source/manifests/strings-raw.txt > workspace/raw/source/manifests/strings-cli-flags.txt
grep -P '"Error|Failed|Warning' workspace/raw/source/manifests/strings-raw.txt > workspace/raw/source/manifests/strings-errors.txt
```
### 5.2 Map Strings to Chunks
```bash
echo '{"string_locations": [' > workspace/raw/source/manifests/string-manifest.json
for chunk in workspace/raw/source/chunks/*.js; do
name=$(basename "$chunk")
echo " {\"chunk\": \"$name\", \"strings\": [" >> workspace/raw/source/manifests/string-manifest.json
grep -oP '"[^"]{10,}"' "$chunk" | head -20 | while read str; do
echo " $str," >> workspace/raw/source/manifests/string-manifest.json
done
echo " ]}," >> workspace/raw/source/manifests/string-manifest.json
done
echo ']}' >> workspace/raw/source/manifests/string-manifest.json
```
## Phase 6: Per-Unit Analysis (all source shapes)
The chunk-analyzer agent runs once per analyzable unit. What counts as a "unit" depends on target shape:
- **Bundle target:** a chunk file from Phase 3, e.g. `workspace/raw/source/chunks/chunk-0042.js`
- **Source tree:** a source file or small module from Phase 3, e.g. `src/parser/lexer.py` or `src/http/handler.go`
- **Decompiled binary:** a decompiled source file from the Decompilation Path
`$UNIT` in the examples below is the path to the unit being analyzed. Grep patterns use conventions common in several languages; adjust to the target language's idioms.
### Exhaustive Reading Requirement (CRITICAL)
**You MUST read every single line of the unit. No exceptions.**
- Do NOT skim. Do NOT skip sections that "look like boilerplate."
- The grep patterns below are for INDEXING, not for UNDERSTANDING.
- After running greps, you MUST read the full unit file.
- Every routine (function, method, class) must be identified and catalogued.
- Every line must be accounted for.
**Verification checklist before writing analysis:**
- [ ] I read the ENTIRE unit, not just samples
- [ ] I identified EVERY function/method/class in the unit
- [ ] I understand what EVERY section of code does
### 6.1 Initial Survey (Then Read in Full)
```bash
wc -l "$UNIT" # Know the size
head -50 "$UNIT" # Get oriented
tail -20 "$UNIT" # See the end
cat "$UNIT" # READ THE ENTIRE FILE
```
### 6.2 Identify Behaviors
```bash
# Domain indicators (informative strings are clues in any language)
grep -oE '"[a-zA-Z]{5,}"' "$UNIT" | sort | uniq -c | sort -rn | head -20
# Error messages
grep -oE '"[^"]*[Ee]rror[^"]*"' "$UNIT" | sort -u
# Common action verbs in method/function invocations
grep -oE '\.(read|write|send|receive|parse|validate|handle|process|create|delete|update)\(' "$UNIT" | sort | uniq -c
```
### 6.3 Catalog Capabilities
Use language-appropriate declaration patterns. Read the matches; don't rely on the grep counts alone.
```bash
# JavaScript / TypeScript
grep -oE "function [a-zA-Z_][a-zA-Z0-9_]*" "$UNIT"
grep -oE "(const|let|var) [a-zA-Z_][a-zA-Z0-9_]* = (async )?(function|\()" "$UNIT"
grep -oE "class [A-Z][a-zA-Z0-9_]*" "$UNIT"
grep -oE "exports\.[a-zA-Z_]+|export (const|function|class|default)" "$UNIT"
# Python
grep -oE "^(async )?def [a-zA-Z_][a-zA-Z0-9_]*" "$UNIT"
grep -oE "^class [A-Z][a-zA-Z0-9_]*" "$UNIT"
# Go
grep -oE "^func (\([^)]+\) )?[A-Za-z_][A-Za-z0-9_]*" "$UNIT"
grep -oE "^type [A-Z][a-zA-Z0-9_]* " "$UNIT"
# Rust
grep -oE "^(pub )?fn [a-z_][a-z0-9_]*" "$UNIT"
grep -oE "^(pub )?(struct|enum|trait) [A-Z][a-zA-Z0-9_]*" "$UNIT"
# Swift
grep -oE "^(public |private |internal )?func [a-z_][a-zA-Z0-9_]*" "$UNIT"
grep -oE "^(public |private |internal )?(class|struct|enum|protocol|actor) [A-Z][a-zA-Z0-9_]*" "$UNIT"
# Java / Kotlin
grep -oE "^(public |private )?(class|interface|enum) [A-Z][a-zA-Z0-9_]*" "$UNIT"
```
### 6.4 Find Dependencies
```bash
# JavaScript / TypeScript
grep -oE "require\(['\"][^'\"]+['\"]\)|from ['\"][^'\"]+['\"]" "$UNIT"
# Python
grep -oE "^(from [a-zA-Z_][a-zA-Z0-9_.]* )?import [a-zA-Z_][a-zA-Z0-9_., ]*" "$UNIT"
# Rust
grep -oE "^use [a-zA-Z_][a-zA-Z0-9_:]+" "$UNIT"
# Swift
grep -oE "^import [A-Z][A-Za-z0-9_]*" "$UNIT"
# Java / Kotlin
grep -oE "^import [a-z][a-zA-Z0-9_.]+" "$UNIT"
# Go: import blocks span multiple lines; read them from the file header
head -50 "$UNIT" | awk '/^import [(\"]/,/^\)$/'
```
### 6.5 Data Flow
Look for I/O, state mutations, and event/signal interaction. The specific idioms vary by language and framework:
```bash
# I/O operations — common verbs across many languages
grep -nE "\.(read|write|get|set|load|save|fetch|send)\b" "$UNIT" | head -20
# Event / signal / pub-sub shapes (varies by language and framework):
# Node EventEmitter: .on('name', ...), .emit('name', ...)
# Python pyee / blinker: .connect(...), .send(...)
# Rust tokio / crossbeam: .notify(...), .subscribe(...)
# Swift NotificationCenter: .post(name:...), .addObserver(...)
# Generic pub/sub: .publish(...), .subscribe(...), .dispatch(...)
grep -nE "\.(on|emit|connect|notify|subscribe|publish|post|dispatch)\(" "$UNIT" | head -20
```
### 6.6 Output Template
Write the analysis to a path that mirrors the unit's origin:
- Bundle target → `workspace/raw/source/analysis/<chunk-name>.md`
- Source tree → `workspace/raw/source/analysis/<module-or-file-path>.md`
```markdown
# Unit Analysis: <unit name>
## Behavioral Summary
[1-2 sentences: What does this unit DO from a user/system perspective?]
## Key Behaviors Identified
### [Behavior 1 Name]
- **What it does**: [behavioral description]
- **Inputs**: [what it accepts]
- **Outputs**: [what it produces]
- **Evidence**: [function names, strings that indicate this]
### [Behavior 2 Name]
- **What it does**: [behavioral description]
- **Inputs**: [what it accepts]
- **Outputs**: [what it produces]
- **Evidence**: [function names, strings that indicate this]
## Data Handled
- Reads: [what data it reads]
- Writes: [what data it writes]
- Transforms: [what transformations it performs]
## Error Conditions
- [Error 1]: "[exact error message]" - when [condition]
- [Error 2]: "[exact error message]" - when [condition]
## Dependencies
- External: [third-party packages or libraries]
- Internal: [other units it references]
## Domain Indicators
Key strings that reveal purpose:
[informative strings]
## Module Guess
This unit likely belongs to the **[module name]** module because:
- [reason 1]
- [reason 2]
## Needs Deep Dive?
- [ ] Yes - complex behavior requiring full spec
- [ ] No - utility code, can be summarized
## Key Claims
| Claim | Source Location | Confidence |
|-------|----------------|------------|
| [behavioral claim] | <unit>:{line} | inferred |
```
## Phase 7: Per-Function Deep Analysis (all source shapes)
The function-analyzer agent runs once per significant function or method. Each invocation analyzes a single routine exhaustively. `$FUNC` is the path to a file containing the routine:
- **Bundle target:** an extracted-function file from Phase B4, e.g. `workspace/raw/source/functions/func-0007-parseConfig.js`.
- **Source tree:** either the containing source file (if small) or a single-routine extraction. For long source files, slice out the routine into a tmp file before analysis so that greps scope to the routine and not to the whole module.
- **Decompiled binary:** same options as source tree — decompiled code lives on disk as files, so treat it accordingly.
### Exhaustive Reading Requirement (CRITICAL)
**You MUST read every single line of the function. No exceptions.**
- Do NOT skim. Read every statement.
- The grep patterns help you INDEX what you find -- they are NOT a substitute for reading.
- Every line of code must be understood.
- Every conditional branch must be traced.
- Every side effect must be identified.
**Verification checklist before writing analysis:**
- [ ] I read the ENTIRE function, line by line
- [ ] I understand what EVERY statement does
- [ ] I traced EVERY conditional branch
- [ ] I identified EVERY side effect
### 7.1 Identify Signature and Parameters
Read the routine's first lines; the signature is in the declaration. Common shapes:
- JavaScript/TypeScript: `function name(params)`, `const name = (params) =>`, `async name(params) {`
- Python: `def name(params):`, `async def name(params):`
- Go: `func name(params) returns`, `func (receiver) name(params) returns`
- Rust: `fn name(params) -> Return`, `pub fn name<T>(params) -> Return`
- Swift: `func name(params) -> Return`, `public func name(params) async throws -> Return`
- Java/Kotlin: `public Return name(params)`, `fun name(params): Return`
### 7.2 Trace Data Flow
```bash
# Parameter identifiers (lowercase tokens are often variables/params)
grep -oE '\b[a-z][a-zA-Z0-9_]*\b' "$FUNC" | sort | uniq -c | sort -rn | head -20
# Return points
grep -nE "^\s*return\b" "$FUNC"
# Call sites (invocations — reads across most languages)
grep -oE "[a-zA-Z_][a-zA-Z0-9_]*\s*\(" "$FUNC" | sort | uniq -c | sort -rn | head -20
```
### 7.3 Identify Side Effects
Idioms are language-specific; adapt:
```bash
# File I/O — common names across languages
grep -nE "\b(read|write|open|close|unlink|remove|mkdir|makedirs|rename)_?[A-Za-z]*\(" "$FUNC"
# Network I/O
grep -nE "\b(fetch|request|Get|Post|Send|httpGet|urlopen|reqwest|URLSession)\b" "$FUNC"
# State mutations
grep -nE "\.(set|push|append|insert|splice|extend|add|update)\(|^\s*[a-zA-Z_][a-zA-Z0-9_.]*\s*=[^=]" "$FUNC"
# Logging
grep -nE "\b(console\.|log\.|logger\.|println!|eprintln!|log\.Printf|logrus\.|zap\.)" "$FUNC"
```
### 7.4 Error Handling
Idioms differ by language — error values in Go and Rust; exceptions in Python, Java, JavaScript, Swift:
```bash
# Exception-based (JS/Python/Java/Swift)
grep -nE "\b(throw|raise)\b" "$FUNC"
grep -cE "\b(try|catch|except|finally)\b" "$FUNC"
# Error-value-based (Go, Rust)
grep -nE "\breturn .*err\b|\\?$|\\?;" "$FUNC"
grep -nE "\bif err != nil\b|\\bResult<|\\bOption<" "$FUNC"
# Guard clauses / precondition checks
grep -nE "\bif\s+(err|e|not|!|.*is None|.*== nil)\b" "$FUNC"
```
### 7.5 Control Flow
```bash
# Conditionals
grep -c "if (" "$FUNC"
grep -c "else" "$FUNC"
# Loops
grep -c "for (\|while (\|\.forEach\|\.map\|\.filter" "$FUNC"
# Early returns
grep -n "return" "$FUNC" | head -10
```
### 7.6 Output Template
Write to `workspace/raw/source/functions/<module-or-unit>/<function-name>.md`:
```markdown
# Function: [name]
## Signature
[function signature with parameters]
## Purpose
[1-2 sentences: What does this function do?]
## Parameters
| Name | Inferred Type | Purpose |
|------|---------------|---------|
| param1 | string | [what it's used for] |
## Return Value
- Type: [inferred]
- Description: [what it returns]
## Behavior
### Normal Path
1. [First thing it does]
2. [Second thing it does]
3. [Returns X]
### Error Paths
- If [condition]: throws [error] / returns [value]
- If [condition]: [behavior]
## Side Effects
- [ ] Modifies parameters
- [ ] Writes to files
- [ ] Makes network calls
- [ ] Mutates external state
- [ ] Logs output
Details:
- [specific side effect 1]
- [specific side effect 2]
## Dependencies
Calls these functions:
- `funcName()` - [purpose]
- `otherFunc()` - [purpose]
## Key Strings
[strings that reveal purpose]
## Complexity
- Lines: [X]
- Conditionals: [X]
- Loops: [X]
- Nested depth: [estimate]
## Behavioral Specification
**Given:** [preconditions]
**When:** function is called with [inputs]
**Then:** [outputs and side effects]
## Key Claims
| Claim | Source Location | Confidence |
|-------|----------------|------------|
| [behavioral claim] | <function-file>:{line} | inferred |
```
## Phase 8: Targeted Module Extraction
When you need focused analysis of a specific component of the target (e.g., "HTTP parser", "error handling", "configuration loader"), rather than analyzing everything in depth. In a bundle, the component is a module identified in Phase B2. In a source tree, it's a named package or directory. In a decompiled binary, it's whichever decompiled files correspond to the focus area. This phase is driven by the targeted-extractor agent.
### 8.1 Scope Assessment
Get a rough sense of how much code relates to the focus area:
```bash
# Count matches for focus-related terms
grep -c "$FOCUS_TERMS" "$TARGET"
# Find which line ranges contain clusters of matches
grep -n "$FOCUS_TERMS" "$TARGET" | awk -F: '{print int($1/100)*100}' | sort -n | uniq -c | sort -rn | head -20
```
This reveals which 100-line regions are most relevant.
### 8.2 String Constant Discovery
Strings are NEVER minified and reveal the most about behavior:
```bash
grep -oE '"[^"]{3,80}"' "$TARGET" | grep -i "$FOCUS_PATTERN" | sort -u
```
Write immediately to `$OUTPUT_DIR/strings.md`.
### 8.3 Identifier Discovery
Named identifiers (functions, classes, properties) often survive minification:
```bash
# Named functions
grep -oE "function [a-zA-Z_]\w*" "$TARGET" | grep -i "$FOCUS_PATTERN" | sort -u
# Property assignments (method definitions)
grep -oE "\.[a-zA-Z_]\w*\s*=" "$TARGET" | grep -i "$FOCUS_PATTERN" | sort -u
# Class definitions
grep -oE "class [a-zA-Z_]\w*" "$TARGET" | grep -i "$FOCUS_PATTERN" | sort -u
```
Write immediately to `$OUTPUT_DIR/identifiers.md`.
### 8.4 Code Section Extraction
For each cluster of focus-area matches, extract surrounding code with enough context to understand the logic (50-100 lines around matches):
```bash
grep -n "$FOCUS_TERM" "$TARGET" | head -30 | while read match; do
LINE=$(echo "$match" | cut -d: -f1)
START=$((LINE - 50))
END=$((LINE + 50))
[ "$START" -lt 1 ] && START=1
sed -n "${START},${END}p" "$TARGET"
echo "--- END EXTRACT (lines $START-$END) ---"
done
```
For each extracted section, read and understand it, then write a summary to `$OUTPUT_DIR/sections/section-NNN.md` with:
- Line range in beautified file
- What this section does (behavioral description)
- Key identifiers and strings found
- Connections to other sections
- Open questions
### 8.5 URL and API Endpoint Extraction
```bash
grep -oE '"https?://[^"]*"' "$TARGET" | sort -u
grep -oE '"wss?://[^"]*"' "$TARGET" | sort -u
grep -oE '"/[a-z][a-z0-9/._-]*"' "$TARGET" | grep -v '\.(js|css|html|png|svg)' | sort -u
```
Write immediately to `$OUTPUT_DIR/endpoints.md`.
### 8.6 Data Structure Extraction
```bash
# Object literals with focus-area properties
grep -oE '\{[^{}]{10,200}\}' "$TARGET" | grep -i "$FOCUS_PATTERN" | head -30
# Property chains revealing structure
grep -oE '\.\w+\.\w+\.\w+' "$TARGET" | grep -i "$FOCUS_PATTERN" | sort | uniq -c | sort -rn | head -30
```
Write immediately to `$OUTPUT_DIR/data-structures.md`.
### 8.7 Error Messages and States Extraction
```bash
# Error strings
grep -oE '"[^"]*[Ee]rror[^"]*"' "$TARGET" | grep -i "$FOCUS_PATTERN" | sort -u
grep -oE '"[^"]*[Ff]ail[^"]*"' "$TARGET" | grep -i "$FOCUS_PATTERN" | sort -u
# Status/state strings
grep -oE '"[^"]*[Ss]tatus[^"]*"' "$TARGET" | grep -i "$FOCUS_PATTERN" | sort -u
```
Write immediately to `$OUTPUT_DIR/errors-and-states.md`.
### 8.8 Contextual Analysis
After extraction, read the extracted sections and produce a synthesis covering:
- **Connection map** -- which sections reference each other; trace call flows and data flows between sections
- **State machine** -- if the module manages state, document the states and transitions observed
- **Protocol/message catalog** -- if the module involves communication, catalog all message types, their fields, and when they are sent/received
- **Configuration points** -- what settings, constants, or configuration values affect this module's behavior
Write synthesis to `$OUTPUT_DIR/analysis.md`.
### 8.9 Findings Report
Write comprehensive findings to `$OUTPUT_DIR/findings.md`:
```markdown
# Targeted Extractor Findings: [Focus Area]
## Target
- Source: [path or module identifier]
- Focus: [area]
## Summary
[2-3 paragraph overview of what was found]
## Key Components
### [Component 1]
- Purpose: [what it does]
- Location: [file:line range or module/package path]
- Key identifiers: [list]
- Key strings: [list]
## Data Model
[Key data structures and their fields]
## Protocol / API
[If applicable: endpoints, message types, wire format]
## State Management
[If applicable: states, transitions, persistence]
## Configuration
[Settings that affect behavior]
## Error Conditions
[What can go wrong and how it's handled]
## Open Questions
[Things that need further investigation]
## Cross-References
[How this component relates to others in the target]
```
## Provenance Rules
### Source Type
All claims from source code analysis use `source=source-code`:
```markdown
- Sessions expire after 30 minutes of inactivity
<!-- cite: source=source-code, ref=workspace/raw/source/analysis/chunk-0011.md:34, confidence=inferred, agent=chunk-analyzer -->
```
### Layer 1 Agents -- Single Source
Targeted-extractor, chunk-analyzer, and function-analyzer are Layer 1 agents. They examine a single source (the source code). Confidence is typically `inferred` because there is only one source to draw from.
### Confidence Levels
- **confirmed** -- exact literal or API call visible in source, OR corroborated by a second independent source (e.g., runtime observation agrees with source reading)
- **inferred** -- derived from code logic; single authoritative source provides direct evidence
- **assumed** -- based on naming convention, comment text, or structural reasoning; not verified against observable behavior
### Cite As You Go
Every behavioral claim gets an inline citation immediately after the claim. Do NOT batch citations at the end of analysis. The moment you write a behavioral assertion, the very next thing you write is the `<!-- cite: -->` comment.
### Key Claims Table
End each analysis file with a Key Claims table:
```markdown
## Key Claims
| Claim | Source Location | Confidence |
|-------|----------------|------------|
| Handles session timeout at 30 min | <unit>:145 | inferred |
| Uses AES-256-GCM for encryption | <unit>:302 | confirmed |
| Salt length is a fixed 16 bytes | <function-file>:{line} | inferred |
```
This table is how downstream verification agents trace claims back to source.
## Output Structure
Output layout varies by target shape.
### Bundle target
```
workspace/raw/source/
target.js # Original (beautified) bundle
chunks/ # Split modules
chunk-0001.js
chunk-0002.js
...
functions/ # Extracted individual functions (>10 lines each)
func-0001-processMessage.js
func-0002-handleRequest.js
...
manifests/ # Inventories
chunk-manifest.json
function-manifest.json
string-manifest.json
strings-raw.txt
strings-urls.txt
strings-constants.txt
strings-cli-flags.txt
strings-errors.txt
function-locations.txt
analysis/ # Per-chunk behavioral analysis
survey.md
chunk-0001.md
chunk-0002.md
...
functions/ # Per-function behavioral analysis
func-0001.md
func-0002.md
...
exploration/ # Targeted explorations by focus area
{focus-area}/
strings.md
identifiers.md
sections/
section-001.md
section-002.md
...
endpoints.md
data-structures.md
errors-and-states.md
analysis.md
findings.md
```
### Source tree target
```
workspace/raw/source/
manifests/
module-manifest.json # List of modules, files, lines, language
analysis/ # Per-module behavioral analysis
survey.md
<module-path-1>.md # e.g. src-parser-lexer.md
<module-path-2>.md
...
functions/ # Per-function analyses, grouped by module
<module-path>/
<function-name>.md
...
exploration/ # Targeted explorations by focus area
{focus-area}/
findings.md
```
The module-path convention flattens the source tree into filenames (e.g., `src/parser/lexer.py` → `src-parser-lexer.md`) so the analysis directory stays flat and greppable.
### Decompiled binary target
Decompiled binaries are handled by first writing decompiled source to `workspace/raw/source/decompiled/` (preserving the decompiler's output layout), then running the shape-appropriate pipeline above: if the decompiled output is a single large file, treat it as a bundle; if the decompiler produced a tree of files, treat it as a source tree.
## Rules
1. **WRITE AS YOU GO** -- every finding goes to a file immediately. Do not accumulate findings in your head. Use the Write tool the moment you have something to record.
2. **Focus on BEHAVIOR not IMPLEMENTATION** -- write "handles authentication" not "calls authLib.verify()". Describe what the code DOES, not how it is structured.
3. **No raw source code excerpts longer than one line** -- behavioral output must not contain multi-line code snippets. Single-line references are acceptable as evidence.
4. **Flag behavioral complexity** -- note what needs deep-dive analysis. Mark chunks and functions that exhibit complex state management, protocol handling, or multi-step workflows.
5. **Reuse beautified code** -- before beautifying, check if a beautified version already exists at `workspace/raw/source/target.js`. Multiple agents share this file.
6. **Exhaustive reading is mandatory** -- grep patterns are for indexing, not understanding. After running greps, you MUST read the full source. Every function, method, class, and code path must be identified.
7. **Cite as you go** -- every behavioral claim gets an inline `<!-- cite: -->` comment immediately after the claim. Never defer citation to a later step.
8. **One chunk/function per invocation** -- chunk-analyzer processes one chunk. function-analyzer processes one function. Stay focused.
9. **Be targeted in exploration** -- the targeted-extractor stays focused on the requested component. Do not analyze the entire target when only one component is needed.
10. **Note line numbers** -- in the beautified file, so sections can be found again by downstream agents and verification.