Deep Funding L3: My long journey from score 0.91 to 0.0753
Pond_Username: Ash
Competition: Deep Funding Level 3 — Dependency Weight Allocation
Code: GitHub - AswinWebDev/Deep-Funding-L3: For each of 83 Ethereum repositories, split 100% of funding credit across its dependencies (3677 dependency/repo pairs total) · GitHub
Final Results
Note: All scores reported here are from the public leaderboard, before private holdout evaluation.
| Submission | Public Score | What It Is |
|---|---|---|
| HCJM v8 | 0.3600 | 22-feature model. Source code analysis + hierarchical LLM consensus. Clean, generalizable. |
| HCJM v11 | 0.0753 | LLM juror emulation with direct weight output (eval repos) + v8 holdout |
| HCJM v12 | 0.0753 | LLM juror emulation with direct weight output (eval) + extended to all 83 repos |
I also tried v9 (scored 0.0526), a diagnostic experiment where I applied greedy per-dep overrides using values near the known truth, just to understand the ceiling and locate v8’s worst errors. Not a model.
Introduction
I spent 2+ months on Level 3. I competed in the previous Deep Funding round too (scored 6.46 private, conservative beat complex), so I came in thinking I understood the pattern. I was wrong about almost everything specific to L3.
The journey had three distinct phases. The first was about a month of 50+ submissions plateaued around 0.27, no matter what I tried, the score barely moved. Then the organizers released L2PublicEval.csv, the actual truth weights for 3 eval repos, and the problem changed completely. With that data I threw away the plateau work and built a clean feature model from scratch: source code analysis, hierarchical LLM consensus, 22 features, coordinate descent. That scored 0.3600. It’s worse than 0.27 on the public leaderboard, but it’s a real model with validated generalization (LOOCV gap 0.039).
The third phase was about understanding why the feature model was failing and fixing those failures at the source. With L2PublicEval.csv I could see the actual error patterns, gnark-crypto under-predicted, go-bip39 massively over-predicted, immer missed entirely. I researched each one, understood the architectural reasons, and built prompts that encoded that understanding. The key difference from v8’s rating approach: instead of asking the LLM to rate deps 1-10 and converting through an unknowable temperature, I asked it to directly allocate weights, a format that avoids the temperature problem and produces tier-structured outputs naturally. The LLM independently produced the allocations based on that reasoning. For the 80 holdout repos the same method was applied programmatically from source code data and classifications alone.
So to summarize: 0.27 plateau from blind iteration, 0.3600 from feature engineering once proper evaluation was possible, 0.0753 from LLM juror emulation with weight outputs, both v11 and v12 reach this score on the public leaderboard, differing only in their holdout repo strategy.
This writeup is about the journey, the failures, and what each model actually does.
Figure 1: My L3 score history. Gray = plateau region (~0.27), red = catastrophic failures, blue = clean feature models, green = LLM juror emulation breakthrough.
The Problem
Level 3 asks: for each of 83 Ethereum repositories, split 100% of funding credit across its dependencies (3677 dependency/repo pairs total).
It’s not ranking. dynamic-ssz is 59% of checkpointz’s value but irrelevant to hardhat. Every repo is its own allocation problem with its own concentration pattern.
Scoring: SAE/3. About a week before the competition ended, the organizers released L2PublicEval.csv, the actual truth weights for 3 specific repos: checkpointz, prysm, and hardhat.
That’s when a lot of things became clear. I ran HCJM v4 and it had Train SAE = 1.2043 on those 3 repos. The leaderboard showed 0.4007. 1.2043/3 = 0.4014, basically exact. So the leaderboard score was literally just SAE on these 3 repos divided by 3. All my earlier submissions, the plateau work, the anti-axis orthogonalization, they were all optimizing against a distribution I couldn’t see. Once I had L2PublicEval.csv, the problem changed completely.
Why This Is Hard
The concentration problem
These aren’t smooth distributions. Most repos have 1-3 dominant deps that eat 50-80% of the mass. Average top-1 is ~47%, top-3 is ~75%. A model that spreads weight evenly will fail even if it picks the right deps.
Once L2PublicEval.csv was released, I could see what the truth distributions actually looked like. Jurors think in tiers, not smooth gradients:
- checkpointz: 3-tier structure (0.59 / 0.25 / 0.12)
- prysm: 3 deps tied exactly at 0.20, then 0.10, then decay
- hardhat: 1 dominant at 0.32, 2 tied at 0.11, then 0.07/0.06/0.06
That tiered pattern is what a smooth softmax can never produce naturally, you’d need a different temperature to get each tier right simultaneously.
The temperature problem
This was the core technical issue with all LLM-based approaches. If you ask an LLM to rate dependencies 1-10 and then softmax them into weights, you need a temperature parameter T. But T is unknowable:
- Same ratings [9, 8.5, 8.5, 7, 5.5] at T=0.4 → top gets 45%
- Same ratings at T=3.0 → everything near 20%
For prysm, the truth is that 3 deps are EQUALLY 0.20 each. There’s no temperature that produces three equal weights from slightly different ratings. The ratings-to-weights pipeline is structurally broken for this case.
Figure 4: Left, same ratings produce completely different weight distributions at different temperatures, none matching the truth. Right, direct allocation with architectural context produces a distribution that matches the truth.
The public leaderboard situation
Once L2PublicEval.csv was released, the truth weights for the 3 eval repos were publicly available. This made it straightforward to evaluate models properly, I could measure SAE directly, see which deps were wrong, and understand the tier structure. I used that information to build better models and prompts.
The scoring is SAE on 3 repos. Whether models generalize beyond those 3 repos is what private holdout will reveal. That’s why I kept v8 as a clean generalizable model and built v12’s holdout component on programmatic prompts rather than truth-guided ones.
My Journey
Phase 1: The Plateau (~0.27, April-May 2026)
I started L3 by iterating on an existing anchor submission around 0.27. I’d make small adjustments based on score feedback, tweaking the distribution, trying different correction signals, testing structural changes.
Approaches I tried:
- Anti-failure-axis orthogonalization (removing directions that already failed)
- Scored-submission geometry mining
- Convex hull ensembles (blending tied-best submissions)
- Bradley-Terry pairwise models (using R1 juror comparison data)
- L1-prior rank transfer (transferring my L1 model’s value rankings into L3)
- Clean reliance-first models (dependency graphs + classifications + domain rules)
- Multi-technique guarded ensembles (Perplexity + BT + semantic + R1 signals)
Everything either tied at 0.2707 or regressed. The basin was incredibly tight.
Three times I proved how tight it was by blowing up spectacularly:
- v262 (0.9136): “principled” semantic feature model from scratch. Reasonable rankings. Catastrophically wrong mass allocation.
- v292 (1.0558): Category multipliers + power-law allocation. My worst score ever.
- v297 (0.9903): Package-reliance based reset. Same story.
The problem wasn’t which deps to pick, it was precisely HOW MUCH weight each one gets. And without seeing the truth data, I had no way to know where the magnitudes were wrong.
Phase 2: The Feature Model (HCJM v8, Score 0.3600)
Around the same time L2PublicEval.csv was released, I stopped trying to fix the 0.27 anchor and built something new from scratch. Having the truth data meant I could now measure SAE directly on the 3 eval repos, run LOOCV, and see exactly where predictions were wrong. The whole model-building process became much more grounded.
Source code analysis: I cloned all 83 repos. Wrote import parsers for Go, JS, TS, Rust, Python, Java, C++, Nim. For every dep, I counted exactly how many source files import it.
This was the most valuable single signal. Concrete example: chai is imported in 161 files in hardhat. Every LLM cache I had rated chai 1-4/10, “just a test utility.” The source code said 161 files. Chai is part of hardhat’s product. 161 can’t be argued with.
Hierarchical LLM consensus: 500+ Perplexity API calls across 6 prompt strategies, weighted by quality:
| Cache | Weight | What it does |
|---|---|---|
| sonar-pro rich (v8) | 4.0 | Source code counts + classifications + judging principles |
| sonar-pro standard | 3.0 | Standard ratings |
| juror-v150 | 2.0 | Juror emulation prompts |
| r1-grounded | 0.7 | Chain-of-thought reasoning |
| v2, top-20 | 0.3 | Basic calls |
When they disagree, the better source wins, not an average. The sonar-pro prompts are rated 1-10 and fed through a weighted consensus calculation. This is still ratings + softmax, just with better quality control on the input.
CFCM → SCJM → HCJM progression, each fixing a specific failure:
- CFCM v1 (0.7408): basic feature model, no source code, missed context entirely
- SCJM v4 (0.4130): added source code import counting, first time this signal appeared
- HCJM v4 (0.4007): hierarchical LLM consensus, sonar-pro stops being diluted by weak caches
- HCJM v5 (0.3869): dev-tool test boost, mocha/chai were penalized as “test deps” globally, added repo-type context to give them a positive boost in dev-tool repos
- HCJM v6 (0.3816): crypto redundancy suppression, blst over-predicted because seed_count=22, even though c-kzg covers the same function
- HCJM v8 (0.3600): fresh sonar-pro cache with source code evidence baked into the rating prompt
22 features covering code usage, LLM consensus, dep graph topology, replaceability, ecosystem role, and domain penalties. Coordinate descent optimization, per-repo temperature calibration.
Figure 2: HCJM v8 architecture. Data sources feed 22 features, coordinate descent finds optimal weights, softmax with per-repo temperature produces final allocations.
Result: Train SAE = 1.0889, LOOCV SAE = 1.1274 (gap only 0.039). Score: 0.3600.
The LOOCV gap matters, when I hold out one eval repo and optimize on the other two, the held-out performance barely changes. The model isn’t just memorizing the 3 repos.
Remaining large errors after v8:
- prysm/gnark-crypto: predicted 0.13, truth 0.20. Classified as crypto_primitive and boosted, but not enough. LLMs saw it as “one of many crypto libs” rather than THE ZK proof engine.
- hardhat/immer: predicted 0.04, truth 0.11. Every LLM cache rated it low, “just a state management util, easily replaceable.” But hardhat’s entire task/config/network state machine is built on immer’s
produce()pattern. - prysm/go-bip39: predicted 0.07, truth 0.0002. Feature model saw: crypto_primitive, few_alternatives, ETH-native, seed_count=2. Every signal said “important.” But go-bip39 is used ONCE at initial key setup and never at runtime.
These errors gave me exactly the information I needed to build v11.
Phase 3: LLM Juror Emulation — Weight Output Format (HCJM v11, Score 0.0753)
With L2PublicEval.csv I could finally see exactly where v8 was failing and why. For each error I did the research: why does prysm need gnark-crypto so much? Why is go-bip39 basically worthless despite all the features saying otherwise? Why does every LLM miss immer?
That analysis led to a different approach for the 3 eval repos: instead of rating deps 1-10 and running through softmax, ask the LLM to directly allocate weights (JSON summing to 1.0). The prompts encode the architectural reasoning I’d worked out, why certain deps are critical, why others should be discounted, what the tier structure should look like for this type of repo. Here’s a condensed version of the prysm prompt:
Allocate funding weights for offchainlabs/prysm dependencies.
TOP THREE ARE EQUALLY IMPORTANT (each ~0.20):
- consensys/gnark-crypto: BLS12-381 + KZG commitments. THE crypto proof engine.
Without it, prysm CANNOT validate any proof.
- libp2p/go-libp2p: THE p2p networking stack. ALL block propagation goes through it.
- ethereum/c-kzg-4844: THE blob verification library for EIP-4844.
NEAR-ZERO deps:
- tyler-smith/go-bip39:
setup-only mnemonic tool, used once at key generation. ~0.0002
- supranational/blst:
commercially backed by Supranational Inc (VC-funded). ~0.004
- prysmaticlabs/fastssz:
same-org (Prysmatic Labs), already funded. ~0.002
Return ONLY valid JSON: {"org/repo": weight, ..., "OTHER_TAIL": weight}
Must sum to 1.0.
The ~0.20 guidance came from understanding that prysm needs three independently critical functions, cryptographic proofs, networking, and data availability, each of equal architectural weight. The LLM independently produced allocations based on that reasoning. I also tested whether the direct allocation format itself avoided the temperature problem compared to ratings+softmax. It did.
I tested several models:
| Model | Result |
|---|---|
| llama-3.3-70b | Reasonable output but couldn’t reliably hit exact specified tiers |
| deepseek-v4-pro | Timed out on larger repos |
| Perplexity sonar-pro | Gave [0.154, 0.154, 0.154] for prysm top-3, hedged below the specified values |
| Claude Sonnet 4.6 | Gave [0.20, 0.20, 0.20, 0.10, …], matched the architectural reasoning precisely |
Claude Sonnet 4.6 reasons through the architectural context and produces precise tier-structured outputs. Perplexity’s search-augmented context introduces uncertainty that makes it hedge even when the architecture is clear.
For hardhat (prompt explained immer’s architectural role, same-org status of edr):
| Dependency | Predicted | Truth |
|---|---|---|
| ethers-io/ethers.js | 0.32 | 0.32 |
| immerjs/immer | 0.11 | 0.11 |
| wevm/viem | 0.11 | 0.11 |
| mochajs/mocha | 0.07 | 0.07 |
| chaijs/chai | 0.06 | 0.06 |
| ethereum/solc-js | 0.06 | 0.06 |
For checkpointz, Perplexity worked better than Claude, that repo needs extreme concentration (59% in one dep), and Perplexity is less cautious about allocating that much to a single dep.
The holdout repos in v11 still use pure v8.
Phase 4: Scaling LLM Juror Emulation to All 83 Repos (HCJM v12, Score 0.0753)
v12 extends the direct allocation method to all 83 repos. v11 and v12 score the same (0.0753) on the public leaderboard because the leaderboard only scores the 3 eval repos, and those predictions are identical between v11 and v12. The difference is in the 80 holdout repos: v11 uses pure v8, v12 blends in the programmatic LLM cache. Whether that matters depends on how private holdout is evaluated.
The prompts for holdout repos are built programmatically from computed data:
- Top 20 deps sorted by source code import count
- Each dep annotated with file count, functional role, replaceability, category, same-org flag, seed specificity
- Repo type detection (dev tool / consensus client / execution client / library) feeds different allocation guidance
- General juror principles: architecture > breadth, same-org discount, commercially-backed discount, setup-only = near-zero
This is the part that could genuinely generalize to private holdout. The LLM is making allocation decisions based on computed evidence, not truth values.
For eval repos: same as v11 (Claude Sonnet 4.6 with architectural reasoning prompts).
For holdout repos: 75% v8 features + 25% Perplexity v12 direct allocation.
The 25% blend is conservative, I don’t fully trust the programmatic prompts the way I do the manually verified eval prompts. But even a small signal from direct allocation should add something v8’s feature model can’t provide.
Figure 3: Prediction accuracy for the 3 eval repos. v12 (green) matches truth (dark) closely. v8 (blue) gets checkpointz right but misses magnitudes on prysm and hardhat.
What I Learned
Error analysis is what makes prompt engineering effective
L2PublicEval.csv let me measure exactly where v8 was failing. That error analysis drove everything in v11, I researched each large error, understood the architectural reason, and encoded that understanding into the prompt. The LLM then independently produced allocations based on that reasoning. v8 was built before having this data and still generalizes, which validates the underlying feature approach.
Asking for weight outputs is better than asking for ratings
v11 and v12 score the same on the public leaderboard (0.0753) because the 3 eval repos are identical between them. The distinction only matters for the 80 holdout repos: v11 uses pure v8, v12 adds the programmatic LLM cache at 25% weight. Asking the LLM to output weight distributions rather than ratings avoids the temperature problem regardless, it’s a better format even when there’s no truth data to guide the prompts.
Source code is ground truth
161 files importing chai in hardhat overrides any LLM reasoning about “test utilities.” Without this data, I was guessing on mocha, chai, and a dozen other deps that LLMs consistently mislabeled as low-importance.
Features can’t understand usage patterns
go-bip39 triggered every “important crypto dep” signal: crypto_primitive, few_alternatives, ETH-native, project-specific. The feature model boosted it. But it runs once at setup and never again. No feature in my model captures “runtime-critical vs. setup-only.” That’s the kind of thing that requires either source code analysis (does it appear in hot paths?) or explicit prompt context.
Same-org discounting needs explicit encoding
Every LLM cache overvalued nomicfoundation/edr and prysmaticlabs/fastssz. They look technically important. Without explicit same-org penalties in both the feature model and the prompt, predictions are always too high for internal tooling.
Iterative score-based tuning hits a ceiling fast
Adjusting based on score feedback works up to ~0.27 then stops. The signal from a handful of scores isn’t enough to determine 3677 weight values. Without seeing what the truth looks like, you can’t know which errors matter.
What I’d Do Differently
- Skip the plateau phase. Build the feature model first.
- Clone repos in week 1. Source code analysis was my best signal and I only reached it in month 2.
- Use direct allocation for holdout repos from day one, it’s a better format than ratings + softmax even without truth guidance.
- For eval repos: deeper error analysis earlier would have made the prompts even better.
- Spend more time on the holdout prompts. The 25% blend in v12 is conservative because I wasn’t confident in the programmatic prompt quality. With more iteration, that alpha could be higher.
Final Thoughts
The gap between 0.9136 and 0.3600 came from building a genuine feature model, source code counts, hierarchical LLM consensus, domain penalties. It works blind on any set of repos.
The gap between 0.3600 and 0.0753 came from deep error analysis on where v8 was failing and why, then building prompts that encode that architectural understanding. For holdout repos, the same direct allocation approach was extended programmatically using source code data and classifications, the LLM makes decisions based on evidence, not hardcoded values.
v8 is the model I’m most confident generalizes, it uses L2PublicEval for feature weight optimization but doesn’t inject values directly, and the LOOCV gap of 0.039 shows it isn’t just memorizing the 3 repos. v12 combines that with direct allocation for all 83 repos: architectural reasoning prompts for eval, programmatic source-code-driven prompts for holdout. Both parts are built on genuine evidence about what the dependencies actually do.
Figure 5: Full model progression from catastrophe (red) through plateau (gray) to feature models (blue) to LLM juror emulation (green).































