2026-08-16 18:12:50 +07:00
from __future__ import annotations
import hashlib
import json
import re
import time
import uuid
from collections import Counter
from decimal import Decimal
from typing import Any
from agents . venture_discovery import RESEARCH_CATEGORIES , VentureDiscoveryService
from control_plane . events . bus import EventBus
from control_plane . ventures . models import (
AutonomousOperabilityAssessment ,
AutonomousGateResult ,
CompanyMandate ,
CompanyProposal ,
CompanyProposalStatus ,
CryptoICDecisionType ,
CryptoJurisdictionPolicy ,
CryptoRedTeamAssessment ,
CryptoScenarioLab ,
2026-08-16 19:31:15 +07:00
CryptoAutonomyClass ,
2026-08-16 18:12:50 +07:00
FounderDependencyLevel ,
OnchainNecessityAssessment ,
PortfolioICReview ,
PortfolioThesis ,
PortfolioThesisStatus ,
ProtocolThesis ,
2026-08-16 19:31:15 +07:00
ProtocolSecurityAssessment ,
ProtocolSecurityDecision ,
2026-08-16 18:12:50 +07:00
ProtocolValueCapture ,
2026-08-16 19:31:15 +07:00
PreTokenMonetizationAssessment ,
PreTokenMonetizationMode ,
2026-08-16 18:12:50 +07:00
TokenDemandLoop ,
2026-08-16 19:31:15 +07:00
TokenEconomicModel ,
TokenLaunchReadinessAssessment ,
TokenLaunchReadinessStatus ,
2026-08-16 18:12:50 +07:00
TokenNecessityClassification ,
2026-08-16 19:31:15 +07:00
TokenRoleDecomposition ,
TokenRoleRequirement ,
2026-08-16 18:12:50 +07:00
TokenomicsSimulation ,
TokenRedTeamFlag ,
TokenUtilityAssessment ,
VentureArtifact ,
VentureCohort ,
VentureCohortMember ,
VentureGenerationRejection ,
NoveltyGateDecision ,
VentureThesis ,
VentureTrack ,
)
from model_router . policy import model_for_role
from model_router . providers import extract_json_object
from model_router . router import ModelCapability , ModelRequestContract , ModelRouter
2026-08-16 19:31:15 +07:00
from research . searxng import SearxngSearchClient , WebPageFetcher
2026-08-16 18:12:50 +07:00
CRYPTO_TERRITORIES = [
2026-08-16 21:56:09 +07:00
" DECENTRALIZED_AI_COMPUTE " ,
" VERIFIABLE_INFERENCE_NETWORKS " ,
" MACHINE_SERVICE_MARKETS " ,
" AGENT_ECONOMIC_IDENTITY " ,
" AUTONOMOUS_AGENT_COMMERCE " ,
2026-08-16 21:00:15 +07:00
" DECENTRALIZED_SECURITY_MARKETS " ,
2026-08-16 21:56:09 +07:00
" SOFTWARE_SECURITY_BONDS " ,
2026-08-16 21:00:15 +07:00
" PROOF_MARKETS " ,
2026-08-16 21:56:09 +07:00
" DECENTRALIZED_DATA_CONTRIBUTION " ,
" MODEL_CONTRIBUTION_NETWORKS " ,
" COMPUTE_CONTRIBUTION_NETWORKS " ,
" DECENTRALIZED_RESOURCE_MARKETS " ,
" BANDWIDTH_STORAGE_RESOURCE_MARKETS " ,
2026-08-16 21:00:15 +07:00
" DECENTRALIZED_INSURANCE_RISK_POOLS " ,
2026-08-16 21:56:09 +07:00
" PROTOCOLIZED_ESCROW " ,
" MACHINE_REPUTATION_WITH_ECONOMIC_STAKE " ,
" PROVIDER_COORDINATION_NETWORKS " ,
" AUTONOMOUS_INFRASTRUCTURE_MARKETS " ,
2026-08-16 18:12:50 +07:00
" OPEN_CRYPTO_CATEGORY " ,
]
ALLOWED_TOKEN_UTILITIES = [
" protocol fee settlement " ,
" staking tied to measurable service quality " ,
" slashing / economic guarantees " ,
" access to scarce network resources " ,
" compute/data marketplace coordination " ,
" collateral " ,
" security budget " ,
" material protocol governance " ,
" contributor/provider rewards " ,
" reputation-backed economic participation " ,
" decentralized marketplace coordination " ,
" machine-to-machine payments " ,
" proof/attestation markets " ,
" protocol-owned infrastructure " ,
" incentive alignment for decentralized supply " ,
]
INSUFFICIENT_TOKEN_UTILITIES = [ " community " , " marketing " , " speculative upside " , " generic rewards " , " token-gated access " , " governance theater " ]
CRYPTO_SCORE_DIMENSIONS = [
" TOKEN_NECESSITY " ,
" REAL_USAGE_DEMAND " ,
" ONCHAIN_NECESSITY " ,
" VALUE_ACCRUAL_QUALITY " ,
" NETWORK_EFFECT_POTENTIAL " ,
" TOKENOMICS_SUSTAINABILITY " ,
" BOOTSTRAPPABILITY " ,
" AUTONOMOUS_OPERABILITY " ,
" SECURITY_MODEL_QUALITY " ,
" REGULATORY_MANAGEABILITY " ,
2026-08-16 19:31:15 +07:00
" PRE_TOKEN_MONETIZATION_POTENTIAL " ,
2026-08-16 18:12:50 +07:00
]
2026-08-16 21:56:09 +07:00
CRYPTO_RESEARCH_CATEGORIES = [ " USER_PAIN " , " EXISTING_PROTOCOLS " , " FAILED_PRECEDENTS " , " TOKEN_UTILITY_PRECEDENTS " , " SECURITY_BOND_PRECEDENTS " , " SLASHING_PRECEDENTS " , " RESOURCE_MARKET_PRECEDENTS " , " PROVIDER_ECONOMICS " , " NETWORK_BOOTSTRAP " , " VALUE_CAPTURE " , " TOKENOMICS_FAILURES " , " SECURITY_INCIDENTS " , " ONCHAIN_ALTERNATIVES " , " OFFCHAIN_ALTERNATIVES " , " LEGAL_REGULATORY " , " PRE_TOKEN_MONETIZATION " ]
STRUCTURAL_TOKEN_ROLES = { " SECURITY_BOND " , " SLASHABLE_COLLATERAL " , " RESOURCE_ALLOCATION " , " MACHINE_ECONOMIC_IDENTITY " , " PROVIDER_ADMISSION " , " DECENTRALIZED_SUPPLY_COORDINATION " }
WEAK_TOKEN_ROLES = { " DEMAND_SIDE_PAYMENT " , " GOVERNANCE " , " PROVIDER_REWARD " , " TREASURY " , " ACCESS " }
TOKEN_UTILITY_SCORE_KEYS = [ " SECURITY_UTILITY " , " COORDINATION_UTILITY " , " COLLATERAL_UTILITY " , " SLASHING_UTILITY " , " RESOURCE_ALLOCATION_UTILITY " , " INCENTIVE_UTILITY " , " NETWORK_BOOTSTRAP_UTILITY " , " VALUE_CAPTURE_UTILITY " , " MACHINE_ECONOMIC_UTILITY " , " GOVERNANCE_UTILITY " , " PAYMENT_UTILITY " , " SPECULATION_DEPENDENCE " ]
2026-08-16 22:59:30 +07:00
TOKEN_JUDGE_REQUIRED_FIELDS = [ " argument_for_native_token " , " argument_against_native_token " , " external_collateral_counterfactual " , " native_token_removed_breaks " , " native_token_removed_explanation " , " material_improvements_over_USDC_ETH " , " native_asset_costs_and_risks " , " final_rationale " ]
2026-08-16 21:00:15 +07:00
PRIMARY_SOURCE_DOMAINS = [ " ethereum.org " , " eips.ethereum.org " , " github.com " , " arxiv.org " , " sec.gov " , " cftc.gov " , " immunefi.com " ]
SOURCE_REJECTION_REASONS = { " IRRELEVANT " : " SOURCE_REJECT_IRRELEVANT " , " WRONG_CATEGORY " : " SOURCE_REJECT_WRONG_CATEGORY " , " LOW_AUTHORITY " : " SOURCE_REJECT_LOW_AUTHORITY " , " SEARCH_NOISE " : " SOURCE_REJECT_SEARCH_NOISE " , " UNPARSABLE " : " SOURCE_REJECT_UNPARSABLE " , " DUPLICATE " : " SOURCE_REJECT_DUPLICATE " }
2026-08-16 19:31:15 +07:00
2026-08-16 18:12:50 +07:00
CRYPTO_SCENARIOS = [
" oracle failure " ,
" validator/provider collusion " ,
" sybil attack " ,
" token price crash " ,
" liquidity collapse " ,
" spam attack " ,
" fee spike " ,
" slashing event " ,
" bad provider output " ,
" treasury exhaustion " ,
" emissions reduction " ,
" bridge dependency failure " ,
" smart contract exploit scenario " ,
" governance capture " ,
]
class CryptoVentureService :
def __init__ ( self , router : ModelRouter | None = None , bus : EventBus | None = None , * , web_research_available : bool = True , generation_model_hint : str | None = None , research_model_hint : str | None = None , final_ic_model_hint : str | None = None ) - > None :
self . router = router
self . bus = bus or EventBus ( )
self . generation_model_hint = generation_model_hint or model_for_role ( " venture_ideation " )
self . research_model_hint = research_model_hint or model_for_role ( " venture_research " )
self . final_ic_model_hint = final_ic_model_hint or model_for_role ( " venture_portfolio_ic " )
self . venture = VentureDiscoveryService ( router , self . bus , web_research_available = web_research_available , research_model_hint = self . research_model_hint , ideation_model_hint = self . generation_model_hint )
def create_crypto_mandate ( self ) - > CompanyMandate :
mandate = CompanyMandate . objects . create (
objective = " Generate crypto-native protocol ventures where onchain execution and a native token are genuinely necessary for real usage, not speculation. " ,
constraints = { " venture_track " : VentureTrack . CRYPTO_PROTOCOL , " no_token_sale " : True , " no_fundraising " : True , " no_mainnet_issuance " : True , " no_us_targeted_activity " : True , " testnet_or_local_only " : True , " no_real_spend " : True , " no_user_contact " : True } ,
optimization_targets = [ " token necessity " , " onchain necessity " , " real usage demand " , " value accrual " , " sustainable tokenomics " , " autonomous operability " , " regulatory manageability " , " security model quality " ] ,
2026-08-16 21:56:09 +07:00
metadata = { " milestone " : " CRYPTO_PROTOCOL_VENTURE_COHORT_V0.3.1 " , " venture_track " : VentureTrack . CRYPTO_PROTOCOL } ,
2026-08-16 18:12:50 +07:00
)
2026-08-16 21:56:09 +07:00
self . _artifact ( None , mandate , " CRYPTO_VENTURE_MANDATE " , " Crypto Protocol Venture V0.3.1 Mandate " , mandate . constraints , " Crypto protocol cohort mandate. Sol-native problem-first ideation and strong native token utility search. No token sale, fundraising, or mainnet issuance. " , " crypto_venture " )
2026-08-16 18:12:50 +07:00
return mandate
def prepare_cohort ( self , * , size : int , graph_run = None , concurrency : int = 2 ) - > VentureCohort :
mandate = self . create_crypto_mandate ( )
2026-08-16 21:56:09 +07:00
cohort_id = f " CPV031- { time . strftime ( ' % Y % m %d % H % M % S ' ) } - { uuid . uuid4 ( ) . hex [ : 8 ] } "
return VentureCohort . objects . create ( cohort_id = cohort_id , mandate = mandate , cohort_size = size , graph_run = graph_run , concurrency = concurrency , status = " PREPARING_CRYPTO " , graph_versions = { " cohort " : " crypto_venture_cohort v3.1 " } , research_policy = { " source_linked_evidence_required " : True , " research_insufficient_if_no_sources " : True , " primary_source_first " : True , " minimum_category_evidence " : " one strong source or multiple independent medium sources " , " crypto_categories " : CRYPTO_RESEARCH_CATEGORIES } , scoring_policy = { " dimensions " : CRYPTO_SCORE_DIMENSIONS , " strict_token_filter " : True , " sol_problem_first_generation " : True , " strong_native_token_utility_required " : True , " structural_roles " : sorted ( STRUCTURAL_TOKEN_ROLES ) } , metadata = { " milestone " : " CRYPTO_PROTOCOL_VENTURE_COHORT_V0.3.1 " , " venture_track " : VentureTrack . CRYPTO_PROTOCOL , " real_spend " : 0 , " real_customer_outreach " : False , " token_sale " : False , " fundraising " : False , " mainnet_issuance " : False , " v02_baseline " : { " raw " : 30 , " crypto_survivors " : 2 , " autonomous_survivors " : 0 , " finalists " : 0 } , " v03_baseline " : { " raw " : 20 , " onchain_rejected " : 5 , " onchain_passed " : 15 , " token_unnecessary " : 12 , " token_optional " : 3 , " crypto_survivors " : 0 , " finalists " : 0 } } )
2026-08-16 18:12:50 +07:00
def generate_protocols ( self , cohort : VentureCohort ) - > list [ CompanyProposal ] :
accepted = [ ]
attempts = 0
2026-08-16 21:00:15 +07:00
model_usage = Counter ( cohort . metrics . get ( " model_usage " , { } ) )
2026-08-16 18:12:50 +07:00
for index in range ( cohort . cohort_size ) :
territory = CRYPTO_TERRITORIES [ index % len ( CRYPTO_TERRITORIES ) ]
2026-08-16 21:00:15 +07:00
payload , source , usage = self . _protocol_payload ( index , territory )
model_usage . update ( usage )
2026-08-16 18:12:50 +07:00
attempts + = 1
proposal = self . _create_proposal ( cohort . mandate , payload , source , territory )
VentureCohortMember . objects . create ( cohort = cohort , proposal = proposal , metadata = { " territory " : territory } )
accepted . append ( proposal )
2026-08-16 21:56:09 +07:00
cohort . metrics = { * * cohort . metrics , " raw_theses " : len ( accepted ) , " raw_target " : cohort . cohort_size , " raw_generated " : len ( accepted ) , " raw_sol_theses " : len ( [ p for p in accepted if p . metadata . get ( " generation_source " ) == " sol " ] ) , " requested_protocol_count " : cohort . cohort_size , " generation_attempts " : attempts , " accepted_protocols " : len ( accepted ) , " duplicate_rejections " : 0 , " token_necessity_rejections " : 0 , " generation_sources " : sorted ( { p . metadata . get ( " generation_source " , " unknown " ) for p in accepted } ) , " model_usage " : dict ( model_usage ) , " sol_generation_requests " : model_usage . get ( " sol_generation_requests " , 0 ) , " sol_onchain_judge_requests " : model_usage . get ( " sol_onchain_judge_requests " , 0 ) , " fallback_count " : model_usage . get ( " fallback_count " , 0 ) }
2026-08-16 18:12:50 +07:00
cohort . status = " PROTOCOLS_GENERATED "
cohort . save ( update_fields = [ " metrics " , " status " , " updated_at " ] )
return accepted
2026-08-16 21:00:15 +07:00
def onchain_necessity_gate ( self , cohort : VentureCohort ) - > list [ OnchainNecessityAssessment ] :
assessments = [ self . onchain_assessment ( member . proposal ) for member in cohort . members . select_related ( " proposal " ) ]
removed = 0
for member in list ( cohort . members . select_related ( " proposal " ) ) :
proposal = member . proposal
assessment = getattr ( proposal , " onchain_assessment " , None ) or self . onchain_assessment ( proposal )
if assessment . onchain_necessity_score < 70 :
VentureGenerationRejection . objects . create ( cohort = cohort , slot_index = member . rank or 0 , attempt = 1 , decision = NoveltyGateDecision . REGENERATE_HARD_EXCLUSION , reason = " removed by onchain necessity gate " , candidate = { " title " : proposal . title , " onchain_necessity_score " : assessment . onchain_necessity_score } , similarity_score = 0.0 )
member . delete ( )
proposal . status = CompanyProposalStatus . REJECTED
2026-08-16 21:56:09 +07:00
proposal . metadata = { * * proposal . metadata , " routed_to_saas " : True , " routed_to_venture_studio " : True , " onchain_rejected " : True , " crypto_failure_reason " : " onchain necessity failed " }
2026-08-16 21:00:15 +07:00
proposal . save ( update_fields = [ " status " , " metadata " , " updated_at " ] )
removed + = 1
2026-08-16 21:56:09 +07:00
onchain_passed = cohort . members . count ( )
cohort . metrics = { * * cohort . metrics , " onchain_rejected " : cohort . metrics . get ( " onchain_rejected " , 0 ) + removed , " onchain_passed " : onchain_passed , " crypto_survivors_after_onchain " : onchain_passed , " token_design_skipped_due_to_onchain_rejection " : cohort . metrics . get ( " token_design_skipped_due_to_onchain_rejection " , 0 ) + removed }
2026-08-16 21:00:15 +07:00
cohort . save ( update_fields = [ " metrics " , " updated_at " ] )
return assessments
2026-08-16 18:12:50 +07:00
def novelty_gate ( self , cohort : VentureCohort ) - > dict [ str , int ] :
removed = 0
hard_excluded = 0
duplicate = 0
seen : dict [ str , CompanyProposal ] = { }
2026-08-16 21:00:15 +07:00
hard_terms = [ " meme " , " generic dex " , " generic l1 " , " generic l2 " , " nft collection " , " yield farm " , " ponzi " , " copycat launchpad " , " speculative asset " , " api reliability slashing pool " , " verimesh " , " verichain " ]
2026-08-16 18:12:50 +07:00
for member in list ( cohort . members . select_related ( " proposal " ) . order_by ( " created_at " ) ) :
proposal = member . proposal
text = self . _proposal_text ( proposal )
2026-08-16 22:33:10 +07:00
utility_text = " " . join ( json . dumps ( item , sort_keys = True , default = str ) if isinstance ( item , dict ) else str ( item ) for item in proposal . protocol_thesis . utility_categories )
fp = self . _fingerprint ( proposal . protocol_thesis . protocol_category + proposal . protocol_thesis . protocol_thesis + utility_text )
2026-08-16 18:12:50 +07:00
reason = " "
decision = None
if any ( term in text for term in hard_terms ) :
hard_excluded + = 1
reason = " hard-excluded crypto thesis "
decision = NoveltyGateDecision . REGENERATE_HARD_EXCLUSION
elif fp in seen :
duplicate + = 1
reason = f " duplicate protocol/token utility thesis: { seen [ fp ] . title } "
decision = NoveltyGateDecision . REGENERATE_DUPLICATE
if decision :
VentureGenerationRejection . objects . create ( cohort = cohort , slot_index = member . rank or 0 , attempt = 1 , decision = decision , reason = reason , candidate = { " title " : proposal . title , " protocol " : proposal . protocol_thesis . protocol_thesis } , similarity_score = 1.0 )
member . delete ( )
proposal . status = CompanyProposalStatus . REJECTED
proposal . save ( update_fields = [ " status " , " updated_at " ] )
removed + = 1
else :
seen [ fp ] = proposal
cohort . metrics = { * * cohort . metrics , " crypto_novelty_removed " : removed , " hard_exclusion_rejections " : cohort . metrics . get ( " hard_exclusion_rejections " , 0 ) + hard_excluded , " duplicate_rejections " : cohort . metrics . get ( " duplicate_rejections " , 0 ) + duplicate }
cohort . save ( update_fields = [ " metrics " , " updated_at " ] )
return { " removed " : removed , " hard_exclusion_rejections " : hard_excluded , " duplicate_rejections " : duplicate }
def regenerate_rejected_slots ( self , cohort : VentureCohort , * , reason : str = " novelty_or_token_gate " ) - > list [ CompanyProposal ] :
2026-08-16 19:31:15 +07:00
created : list [ CompanyProposal ] = [ ]
2026-08-16 21:56:09 +07:00
cohort . metrics = { * * cohort . metrics , " regeneration_attempts " : cohort . metrics . get ( " regeneration_attempts " , 0 ) , " regenerated_protocols " : cohort . metrics . get ( " regenerated_protocols " , 0 ) , " crypto_survivors " : cohort . members . count ( ) , " unfilled_slots_after_regeneration " : max ( 0 , cohort . cohort_size - cohort . members . count ( ) ) , " regeneration_policy " : " V0.3.1 uses total raw Sol generation budget; offchain or weak token ideas are not force-filled. " }
2026-08-16 18:12:50 +07:00
cohort . save ( update_fields = [ " metrics " , " updated_at " ] )
return created
def token_necessity_gate ( self , cohort : VentureCohort ) - > list [ TokenUtilityAssessment ] :
2026-08-16 21:56:09 +07:00
model_usage = Counter ( cohort . metrics . get ( " model_usage " , { } ) )
before = cohort . members . count ( )
assessments = [ ]
for member in cohort . members . select_related ( " proposal " ) :
if not member . proposal . metadata . get ( " crypto " , { } ) . get ( " token_design_completed " ) :
used = self . derive_token_design ( member . proposal )
model_usage . update ( used )
assessments . append ( self . assess_token_necessity ( member . proposal ) )
model_usage [ " sol_token_utility_judge_requests " ] + = 1 if self . final_ic_model_hint == " sol " else 0
2026-08-16 18:12:50 +07:00
removed = self . _remove_weak_token_members ( cohort )
2026-08-16 21:56:09 +07:00
cohort . metrics = { * * cohort . metrics , * * removed , " token_design_attempts " : cohort . metrics . get ( " token_design_attempts " , 0 ) + before , " token_design_count_matches_onchain_passed " : ( cohort . metrics . get ( " token_design_attempts " , 0 ) + before ) == cohort . metrics . get ( " onchain_passed " , before ) , " model_usage " : dict ( model_usage ) , " sol_token_design_requests " : model_usage . get ( " sol_token_design_requests " , 0 ) , " sol_token_utility_judge_requests " : model_usage . get ( " sol_token_utility_judge_requests " , 0 ) }
2026-08-16 18:12:50 +07:00
cohort . save ( update_fields = [ " metrics " , " updated_at " ] )
return assessments
2026-08-16 21:56:09 +07:00
def derive_token_design ( self , proposal : CompanyProposal ) - > Counter :
usage = Counter ( )
crypto = proposal . metadata . get ( " crypto " , { } )
passes = crypto . get ( " generation_passes " , { } ) if isinstance ( crypto , dict ) else { }
pass_a = passes . get ( " pass_a_problem_network " , { } ) if isinstance ( passes , dict ) else { }
pass_b = passes . get ( " pass_b_onchain " , { } ) if isinstance ( passes , dict ) else { }
pass_c_prompt = " PASS C - MINIMAL DECENTRALIZED PROTOCOL ARCHITECTURE. Return JSON with protocol_architecture, participant_model, verification_model, settlement_model, resource_allocation_model, dispute_model, value_capture_model, autonomous_operating_loop. No token design yet. Thesis: " + json . dumps ( { " problem " : pass_a or proposal . pitch , " onchain_review " : pass_b } , default = str )
architecture = self . _model_json ( self . generation_model_hint , pass_c_prompt , purpose = ModelCapability . REASONING )
pass_d_prompt = " PASS D - NATIVE TOKEN UTILITY DESIGN. Derive the minimum native token utility only if it performs strong structural economic or security functions. Explore SECURITY_BOND, SLASHABLE_COLLATERAL, PROVIDER_ADMISSION, RESOURCE_ALLOCATION, MACHINE_ECONOMIC_IDENTITY, CONTRIBUTION_ACCOUNTING, SECURITY_BUDGET, PROTOCOL_FEE_ASSET, PROVIDER_REWARD, DEMAND_SIDE_PAYMENT, GOVERNANCE, ACCESS, TREASURY, OTHER. Payment/governance/rewards/access alone are insufficient. Return JSON with token_thesis, token_utility list, token_demand_loop list, value_capture, token_roles object where each role is REQUIRED/STRONGLY_USEFUL/USEFUL/OPTIONAL/UNNECESSARY, mechanism_fingerprint object, security_model, regulatory_risks. Architecture: " + json . dumps ( architecture or pass_a or proposal . pitch , default = str )
token_design = self . _model_json ( self . generation_model_hint , pass_d_prompt , purpose = ModelCapability . REASONING )
usage [ " sol_protocol_architecture_requests " if self . generation_model_hint == " sol " else " qwen_requests " ] + = 1
usage [ " sol_token_design_requests " if self . generation_model_hint == " sol " else " qwen_requests " ] + = 1
if token_design :
crypto = { * * crypto , " generation_passes " : { * * passes , " pass_c_protocol_architecture " : architecture , " pass_d_token_utility " : token_design } , " token_design_completed " : True , " token_roles " : token_design . get ( " token_roles " , { } ) , " mechanism_fingerprint " : token_design . get ( " mechanism_fingerprint " , { } ) }
proposal . metadata = { * * proposal . metadata , " crypto " : crypto }
proposal . pitch = { * * proposal . pitch , " Token thesis " : str ( token_design . get ( " token_thesis " , proposal . pitch . get ( " Token thesis " , " " ) ) ) , " Token demand loop " : self . _as_list ( token_design . get ( " token_demand_loop " ) or proposal . pitch . get ( " Token demand loop " , [ ] ) ) }
proposal . save ( update_fields = [ " metadata " , " pitch " , " updated_at " ] )
if hasattr ( proposal , " protocol_thesis " ) :
proposal . protocol_thesis . token_thesis = str ( token_design . get ( " token_thesis " , proposal . protocol_thesis . token_thesis ) )
proposal . protocol_thesis . utility_categories = self . _as_list ( token_design . get ( " token_utility " ) or proposal . protocol_thesis . utility_categories )
proposal . protocol_thesis . save ( update_fields = [ " token_thesis " , " utility_categories " , " updated_at " ] )
if hasattr ( proposal , " token_demand_loop " ) :
proposal . token_demand_loop . loop = self . _as_list ( token_design . get ( " token_demand_loop " ) or proposal . token_demand_loop . loop )
proposal . token_demand_loop . save ( update_fields = [ " loop " , " updated_at " ] )
return usage
2026-08-16 18:12:50 +07:00
def _remove_weak_token_members ( self , cohort : VentureCohort ) - > dict [ str , int ] :
unnecessary = 0
optional = 0
2026-08-16 21:56:09 +07:00
essential = 0
strongly = 0
2026-08-16 18:12:50 +07:00
for member in list ( cohort . members . select_related ( " proposal " ) ) :
proposal = member . proposal
assessment = getattr ( proposal , " token_utility_assessment " , None ) or self . assess_token_necessity ( proposal )
if assessment . classification not in { TokenNecessityClassification . TOKEN_ESSENTIAL , TokenNecessityClassification . TOKEN_STRONGLY_JUSTIFIED } :
if assessment . classification == TokenNecessityClassification . TOKEN_OPTIONAL :
optional + = 1
else :
unnecessary + = 1
VentureGenerationRejection . objects . create ( cohort = cohort , slot_index = member . rank or 0 , attempt = 1 , decision = NoveltyGateDecision . REGENERATE_HARD_EXCLUSION , reason = f " removed by token necessity gate: { assessment . classification } " , candidate = { " title " : proposal . title , " classification " : assessment . classification } , similarity_score = 0.0 )
member . delete ( )
proposal . status = CompanyProposalStatus . REJECTED
2026-08-16 21:56:09 +07:00
proposal . metadata = { * * proposal . metadata , " routed_to_saas " : assessment . classification == TokenNecessityClassification . TOKEN_OPTIONAL , " routed_to_venture_studio " : True , " crypto_failure_reason " : f " token classification { assessment . classification } " }
2026-08-16 18:12:50 +07:00
proposal . save ( update_fields = [ " status " , " metadata " , " updated_at " ] )
2026-08-16 21:56:09 +07:00
elif assessment . classification == TokenNecessityClassification . TOKEN_ESSENTIAL :
essential + = 1
else :
strongly + = 1
return { " token_unnecessary_rejections " : cohort . metrics . get ( " token_unnecessary_rejections " , 0 ) + unnecessary , " token_optional_route_to_saas " : cohort . metrics . get ( " token_optional_route_to_saas " , 0 ) + optional , " token_essential " : cohort . metrics . get ( " token_essential " , 0 ) + essential , " token_strongly_justified " : cohort . metrics . get ( " token_strongly_justified " , 0 ) + strongly , " serious_crypto_survivors " : cohort . members . count ( ) , " crypto_survivors " : cohort . members . count ( ) }
2026-08-16 18:12:50 +07:00
def light_market_research ( self , cohort : VentureCohort ) - > None :
started = time . monotonic ( )
total_sources = 0
2026-08-16 19:31:15 +07:00
total_rejected = 0
2026-08-16 18:12:50 +07:00
insufficient = 0
for member in cohort . members . select_related ( " proposal " ) :
2026-08-16 19:31:15 +07:00
research = self . crypto_research ( member . proposal , depth = " light " )
2026-08-16 18:12:50 +07:00
total_sources + = len ( research . get ( " sources " , [ ] ) )
2026-08-16 19:31:15 +07:00
total_rejected + = len ( research . get ( " source_rejections " , [ ] ) )
2026-08-16 18:12:50 +07:00
if not research . get ( " sources " ) :
insufficient + = 1
2026-08-16 19:31:15 +07:00
cohort . metrics = { * * cohort . metrics , " crypto_light_research_seconds " : round ( time . monotonic ( ) - started , 2 ) , " crypto_light_research_sources " : total_sources , " crypto_light_research_rejected_sources " : total_rejected , " research_insufficient_count " : insufficient , " research_survivors " : cohort . members . count ( ) - insufficient }
2026-08-16 18:12:50 +07:00
cohort . save ( update_fields = [ " metrics " , " updated_at " ] )
def protocol_research ( self , cohort : VentureCohort ) - > None :
for member in cohort . members . select_related ( " proposal " ) :
self . _update_protocol_research_flags ( member . proposal )
2026-08-16 19:31:15 +07:00
def crypto_research ( self , proposal : CompanyProposal , * , depth : str = " light " ) - > dict [ str , Any ] :
query_plan = self . crypto_query_plan ( proposal , depth = depth )
client = SearxngSearchClient . from_resources ( )
fetcher = WebPageFetcher ( )
all_sources = [ ]
query_results = [ ]
engine_health = Counter ( )
2026-08-16 21:00:15 +07:00
circuit_breaker = Counter ( )
avoided = 0
primary_sources = self . primary_source_seed_sources ( proposal , query_plan )
all_sources . extend ( primary_sources )
2026-08-16 19:31:15 +07:00
if client is not None :
per_query_limit = 4 if depth == " deep " else 2
for category , queries in query_plan . items ( ) :
for query in queries :
2026-08-16 22:46:24 +07:00
if circuit_breaker and all ( count > = ( 8 if depth == " deep " else 4 ) for count in circuit_breaker . values ( ) ) :
2026-08-16 21:00:15 +07:00
avoided + = 1
2026-08-16 22:46:24 +07:00
query_results . append ( { " category " : category , " query " : query , " status " : " AVOIDED_DUE_TO_ENGINE_FAILURE " , " result_count " : 0 , " tripped_engines " : dict ( circuit_breaker ) } )
2026-08-16 21:00:15 +07:00
continue
2026-08-16 19:31:15 +07:00
try :
payload = client . search_payload ( query )
except Exception as exc :
query_results . append ( { " category " : category , " query " : query , " status " : " SEARCH_INFRASTRUCTURE_FAILED " , " error " : str ( exc ) , " result_count " : 0 } )
continue
unresponsive = payload . get ( " unresponsive_engines " , [ ] ) if isinstance ( payload , dict ) else [ ]
for engine , reason in unresponsive :
2026-08-16 21:00:15 +07:00
status = self . _engine_status ( str ( reason ) )
engine_health [ status ] + = 1
if status in { " CAPTCHA " , " RATE_LIMITED " , " ACCESS_DENIED " } :
2026-08-16 22:46:24 +07:00
circuit_breaker [ str ( engine ) ] + = 1
2026-08-16 19:31:15 +07:00
raw_results = payload . get ( " results " , [ ] ) if isinstance ( payload , dict ) else [ ]
query_results . append ( { " category " : category , " query " : query , " status " : " SEARCH_WORKED " , " result_count " : len ( raw_results ) , " unresponsive_engines " : unresponsive } )
for item in raw_results [ : per_query_limit ] :
if isinstance ( item , dict ) and item . get ( " url " ) :
all_sources . append ( { " type " : " public_web " , " source " : " searxng " , " url " : str ( item [ " url " ] ) , " title " : str ( item . get ( " title " , " " ) ) , " category " : category , " summary " : str ( item . get ( " content " , item . get ( " snippet " , " " ) ) ) , " fallback_evidence " : False } )
2026-08-16 21:00:15 +07:00
pages = fetcher . fetch_many ( all_sources , max_pages = 14 if depth == " deep " else 7 ) if all_sources else [ ]
2026-08-16 19:31:15 +07:00
page_by_url = { page [ " url " ] : page for page in pages }
accepted = [ ]
rejected = [ ]
seen = set ( )
for source in all_sources :
url = source . get ( " url " )
if not url or url in seen :
2026-08-16 21:00:15 +07:00
if url in seen :
rejected . append ( { * * source , " quality " : " reject " , " rejection_reason " : SOURCE_REJECTION_REASONS [ " DUPLICATE " ] , " relevance_score " : 0 } )
2026-08-16 19:31:15 +07:00
continue
seen . add ( url )
enriched = { * * source , * * ( { " content " : page_by_url [ url ] . get ( " text " , " " ) } if url in page_by_url else { } ) }
quality = self . crypto_source_quality ( proposal , enriched )
if quality [ " accepted " ] :
2026-08-16 21:00:15 +07:00
accepted . append ( { * * enriched , " quality " : quality [ " quality " ] , " source_tier " : quality . get ( " source_tier " , source . get ( " source_tier " , " TIER_C " ) ) , " relevance_score " : quality [ " score " ] , " acceptance_reason " : quality [ " reason " ] } )
2026-08-16 19:31:15 +07:00
else :
rejected . append ( { * * enriched , " quality " : " weak " , " rejection_reason " : quality [ " reason " ] , " relevance_score " : quality [ " score " ] } )
2026-08-16 21:00:15 +07:00
category_sources = { category : [ source for source in accepted if source . get ( " category " ) == category ] for category in CRYPTO_RESEARCH_CATEGORIES }
coverage_confidence = { category : self . category_coverage_confidence ( sources ) for category , sources in category_sources . items ( ) }
coverage = { category : confidence in { " MEDIUM " , " HIGH " } for category , confidence in coverage_confidence . items ( ) }
2026-08-16 19:31:15 +07:00
coverage_ratio = round ( sum ( 1 for value in coverage . values ( ) if value ) / len ( CRYPTO_RESEARCH_CATEGORIES ) , 2 )
acceptance_rate = round ( len ( accepted ) / max ( 1 , len ( accepted ) + len ( rejected ) ) , 2 )
search_infrastructure_failed = client is None or ( not all_sources and any ( item . get ( " status " ) == " SEARCH_INFRASTRUCTURE_FAILED " for item in query_results ) )
evidence_insufficient = len ( accepted ) == 0 or coverage_ratio < ( 0.7 if depth == " deep " else 0.25 )
2026-08-16 22:46:24 +07:00
research = { " query_plan " : query_plan , " query_results " : query_results , " sources " : accepted , " source_rejections " : rejected , " source_count " : len ( accepted ) , " source_rejection_count " : len ( rejected ) , " page_fetch_count " : len ( pages ) , " search_result_count " : len ( all_sources ) , " primary_source_count " : len ( [ s for s in accepted if s . get ( " source_tier " ) == " TIER_A " ] ) , " coverage " : coverage , " coverage_ratio " : coverage_ratio , " coverage_confidence " : coverage_confidence , " category_coverage_confidence " : coverage_confidence , " source_provider_health " : " SEARCH_INFRASTRUCTURE_FAILED " if search_infrastructure_failed else " SEARCH_WORKED " , " search_engine_health " : dict ( engine_health ) , " engine_circuit_breaker_events " : dict ( circuit_breaker ) , " queries_avoided_due_to_engine_failure " : avoided , " queries_avoided_due_to_circuit_breaker " : avoided , " source_acceptance_rate " : acceptance_rate , " research_status " : " SEARCH_INFRASTRUCTURE_FAILED " if search_infrastructure_failed else " EVIDENCE_INSUFFICIENT " if evidence_insufficient else " SOURCE_LINKED " , " unverified_categories " : [ category for category , ok in coverage . items ( ) if not ok ] }
2026-08-16 19:31:15 +07:00
proposal . market_evidence = [ * self . _as_list ( proposal . market_evidence ) , * accepted , { " type " : " crypto_research_coverage " , " source " : " crypto_research " , " summary " : f " { depth } crypto research coverage { coverage_ratio } " , " coverage " : coverage , " depth " : depth } ]
proposal . metadata = { * * proposal . metadata , " research " : research }
proposal . save ( update_fields = [ " market_evidence " , " metadata " , " updated_at " ] )
self . _artifact ( proposal , proposal . mandate , " CRYPTO_MARKET_RESEARCH " , f " Crypto Research ( { depth } ) " , research , f " Crypto research { depth } : { len ( accepted ) } accepted, { len ( rejected ) } rejected, coverage { coverage_ratio } . " , " crypto_research " )
return research
def crypto_query_plan ( self , proposal : CompanyProposal , * , depth : str ) - > dict [ str , list [ str ] ] :
crypto = proposal . metadata . get ( " crypto " , { } )
2026-08-16 21:00:15 +07:00
seed = " " . join ( [ str ( crypto . get ( " territory " , " " ) ) , proposal . protocol_thesis . protocol_category , proposal . problem , proposal . target_customer ] ) . replace ( " _ " , " " )
seed = seed . replace ( proposal . title , " " )
seed = re . sub ( r " \ s+ " , " " , seed ) . strip ( ) [ : 120 ]
2026-08-16 19:31:15 +07:00
terms = {
2026-08-16 21:00:15 +07:00
" USER_PAIN " : [ f " { seed } user pain " , f " { proposal . target_customer } coordination failure " ] ,
" EXISTING_PROTOCOLS " : [ f " { seed } protocol documentation " , f " { seed } crypto protocol precedent " ] ,
2026-08-16 19:31:15 +07:00
" FAILED_PRECEDENTS " : [ f " { seed } failed crypto project " , f " { seed } postmortem " ] ,
2026-08-16 21:00:15 +07:00
" ONCHAIN_ALTERNATIVES " : [ f " { seed } onchain escrow settlement attestation " ] ,
" OFFCHAIN_ALTERNATIVES " : [ f " { seed } SaaS alternative " , f " { seed } offchain alternative " ] ,
2026-08-16 19:31:15 +07:00
" TOKEN_MODELS " : [ f " { seed } token model staking " , f " { seed } tokenomics " ] ,
2026-08-16 21:00:15 +07:00
" COLLATERAL_MODELS " : [ f " { seed } collateral model stablecoin ETH staking " ] ,
" STAKING_SLASHING_PRECEDENTS " : [ f " { seed } staking slashing " , f " objective slashing crypto protocol " ] ,
2026-08-16 19:31:15 +07:00
" PROVIDER_ECONOMICS " : [ f " { seed } provider economics " , f " decentralized provider marketplace economics " ] ,
" NETWORK_BOOTSTRAP " : [ f " { seed } network bootstrap " , f " crypto protocol bootstrap supply demand " ] ,
2026-08-16 21:00:15 +07:00
" SECURITY_FAILURES " : [ f " { seed } security incident " , f " { seed } exploit postmortem " ] ,
2026-08-16 19:31:15 +07:00
" LEGAL_REGULATORY " : [ f " { seed } token regulatory risk " , f " crypto staking slashing regulatory " ] ,
" TOKEN_LAUNCH_PRECEDENTS " : [ f " { seed } token launch " , f " protocol token launch precedent " ] ,
2026-08-16 21:00:15 +07:00
" PRE_TOKEN_MONETIZATION " : [ f " { seed } paid beta " , f " crypto protocol pre token revenue " ] ,
2026-08-16 19:31:15 +07:00
}
limit = 4 if depth == " deep " else 2
return { category : queries [ : limit ] for category , queries in terms . items ( ) }
2026-08-16 21:00:15 +07:00
def primary_source_seed_sources ( self , proposal : CompanyProposal , query_plan : dict [ str , list [ str ] ] ) - > list [ dict [ str , Any ] ] :
seeds = [ ]
category_urls = {
" ONCHAIN_ALTERNATIVES " : [ " https://ethereum.org/en/developers/docs/ " , " https://eips.ethereum.org/ " ] ,
" TOKEN_MODELS " : [ " https://ethereum.org/en/developers/docs/standards/tokens/ " ] ,
" COLLATERAL_MODELS " : [ " https://ethereum.org/en/defi/ " ] ,
" STAKING_SLASHING_PRECEDENTS " : [ " https://ethereum.org/en/staking/ " ] ,
" SECURITY_FAILURES " : [ " https://immunefi.com/blog/ " , " https://github.com/pcaversaccio/reentrancy-attacks " ] ,
" LEGAL_REGULATORY " : [ " https://www.sec.gov/newsroom " , " https://www.cftc.gov/PressRoom/PressReleases " ] ,
}
for category in query_plan :
for url in category_urls . get ( category , [ ] ) [ : 2 ] :
seeds . append ( { " type " : " primary_seed " , " source " : " primary_source_seed " , " source_tier " : " TIER_A " , " url " : url , " title " : url , " category " : category , " summary " : " Primary-source seed for crypto protocol research. " , " fallback_evidence " : False } )
return seeds
2026-08-16 19:31:15 +07:00
def crypto_source_quality ( self , proposal : CompanyProposal , source : dict [ str , Any ] ) - > dict [ str , Any ] :
text = " " . join ( str ( source . get ( key , " " ) ) for key in [ " title " , " summary " , " content " , " url " ] ) . lower ( )
url = str ( source . get ( " url " , " " ) ) . lower ( )
2026-08-16 21:00:15 +07:00
category = str ( source . get ( " category " , " " ) )
2026-08-16 19:31:15 +07:00
if any ( noisy in url for noisy in [ " pinterest " , " facebook.com " , " instagram.com " , " x.com/intent " , " webcache " , " archive.org " , " youtube.com/watch " ] ) :
2026-08-16 21:00:15 +07:00
return { " accepted " : False , " score " : 0.0 , " reason " : SOURCE_REJECTION_REASONS [ " SEARCH_NOISE " ] }
source_tier = self . source_tier ( url , text )
preferred = [ " docs " , " github " , " whitepaper " , " paper " , " postmortem " , " audit " , " security " , " research " , " protocol " , " token " , " staking " , " slashing " , " stablecoin " , " collateral " , " attestation " , " oracle " , " eip " ]
2026-08-16 19:31:15 +07:00
proposal_terms = set ( re . findall ( r " [a-z0-9] { 5,} " , self . _proposal_text ( proposal ) ) )
source_terms = set ( re . findall ( r " [a-z0-9] { 5,} " , text ) )
overlap = len ( proposal_terms & source_terms )
2026-08-16 21:00:15 +07:00
category_terms = set ( re . findall ( r " [a-z0-9] { 5,} " , category . lower ( ) . replace ( " _ " , " " ) ) )
category_overlap = len ( category_terms & source_terms )
2026-08-16 19:31:15 +07:00
preferred_hits = sum ( 1 for term in preferred if term in text or term in url )
2026-08-16 21:00:15 +07:00
score = round ( min ( 1.0 , overlap * 0.025 + category_overlap * 0.12 + preferred_hits * 0.08 + ( 0.18 if source_tier == " TIER_A " else 0.08 if source_tier == " TIER_B " else 0 ) ) , 2 )
if category and category_overlap == 0 and source_tier == " TIER_C " and score < 0.45 :
return { " accepted " : False , " score " : score , " reason " : SOURCE_REJECTION_REASONS [ " WRONG_CATEGORY " ] }
if score > = 0.45 :
return { " accepted " : True , " quality " : " strong " , " source_tier " : source_tier , " score " : score , " reason " : " strong category-relevant crypto primary/technical evidence " }
if score > = 0.28 and source_tier in { " TIER_A " , " TIER_B " } :
return { " accepted " : True , " quality " : " medium " , " source_tier " : source_tier , " score " : score , " reason " : " medium authority category evidence " }
if source_tier == " TIER_C " :
return { " accepted " : False , " score " : score , " reason " : SOURCE_REJECTION_REASONS [ " LOW_AUTHORITY " ] }
return { " accepted " : False , " score " : score , " reason " : SOURCE_REJECTION_REASONS [ " IRRELEVANT " ] }
def source_tier ( self , url : str , text : str ) - > str :
if any ( domain in url for domain in PRIMARY_SOURCE_DOMAINS ) or any ( marker in url for marker in [ " /docs " , " docs. " , " whitepaper " , " forum. " , " research. " ] ) :
return " TIER_A "
if any ( marker in text or marker in url for marker in [ " audit " , " postmortem " , " technical research " , " security research " , " protocol research " ] ) :
return " TIER_B "
return " TIER_C "
def category_coverage_confidence ( self , sources : list [ dict [ str , Any ] ] ) - > str :
strong = len ( [ source for source in sources if source . get ( " quality " ) == " strong " ] )
medium_domains = { self . _domain ( str ( source . get ( " url " , " " ) ) ) for source in sources if source . get ( " quality " ) == " medium " }
if strong > = 2 :
return " HIGH "
if strong > = 1 or len ( medium_domains ) > = 2 :
return " MEDIUM "
if sources :
return " LOW "
return " NONE "
def _domain ( self , url : str ) - > str :
return re . sub ( r " ^https?://(www \ .)? " , " " , url . lower ( ) ) . split ( " / " ) [ 0 ]
2026-08-16 19:31:15 +07:00
def _engine_status ( self , reason : str ) - > str :
lowered = reason . lower ( )
if " captcha " in lowered :
return " CAPTCHA "
if " rate " in lowered or " too many " in lowered :
return " RATE_LIMITED "
if " denied " in lowered :
return " ACCESS_DENIED "
if " timeout " in lowered :
return " TIMEOUT "
if " protocol " in lowered :
return " PROTOCOL_ERROR "
if " disabled " in lowered :
return " DISABLED "
return " UNAVAILABLE "
2026-08-16 18:12:50 +07:00
def token_red_team ( self , cohort : VentureCohort ) - > list [ CryptoRedTeamAssessment ] :
2026-08-16 21:56:09 +07:00
assessments = [ ]
for member in cohort . members . select_related ( " proposal " ) :
token = getattr ( member . proposal , " token_utility_assessment " , None )
if token and token . classification in { TokenNecessityClassification . TOKEN_ESSENTIAL , TokenNecessityClassification . TOKEN_STRONGLY_JUSTIFIED } :
assessments . append ( self . red_team_proposal ( member . proposal ) )
2026-08-16 18:12:50 +07:00
counts = Counter ( flag for item in assessments for flag in item . flags )
2026-08-16 21:56:09 +07:00
cohort . metrics = { * * cohort . metrics , " token_red_team_failures " : dict ( counts ) , " token_red_team_count " : len ( assessments ) , " sol_token_red_team_requests " : len ( assessments ) if self . final_ic_model_hint == " sol " else 0 }
2026-08-16 18:12:50 +07:00
cohort . save ( update_fields = [ " metrics " , " updated_at " ] )
return assessments
def tokenomics_simulation ( self , cohort : VentureCohort ) - > list [ TokenomicsSimulation ] :
2026-08-16 19:31:15 +07:00
simulations = [ ]
for member in cohort . members . select_related ( " proposal " ) :
self . assess_pretoken_monetization ( member . proposal )
self . token_role_decomposition ( member . proposal )
self . token_economic_model ( member . proposal )
simulations . append ( self . simulate_tokenomics ( member . proposal ) )
self . token_launch_readiness ( member . proposal )
2026-08-16 18:12:50 +07:00
self . crypto_scenario_lab ( cohort )
return simulations
def crypto_ic_first_pass ( self , cohort : VentureCohort ) - > None :
for member in cohort . members . select_related ( " proposal " ) :
row = self . crypto_score_row ( member . proposal )
member . portfolio_score = row [ " crypto_ic_score " ]
member . metadata = { * * member . metadata , " crypto_first_pass " : row }
member . save ( update_fields = [ " portfolio_score " , " metadata " , " updated_at " ] )
def top5_deep_research ( self , cohort : VentureCohort ) - > None :
before = { }
after = { }
members = list ( cohort . members . select_related ( " proposal " ) . order_by ( " -portfolio_score " , " created_at " ) [ : 5 ] )
for member in members :
before [ str ( member . proposal_id ) ] = member . proposal . metadata . get ( " research " , { } ) . get ( " coverage_ratio " , 0.0 )
2026-08-16 19:31:15 +07:00
self . crypto_research ( member . proposal , depth = " deep " )
2026-08-16 18:12:50 +07:00
after [ str ( member . proposal_id ) ] = member . proposal . metadata . get ( " research " , { } ) . get ( " coverage_ratio " , 0.0 )
cohort . metrics = { * * cohort . metrics , " top5_deep_research_count " : len ( members ) , " top5_research_coverage_before " : before , " top5_research_coverage_after " : after }
cohort . save ( update_fields = [ " metrics " , " updated_at " ] )
def portfolio_crypto_ic ( self , cohort : VentureCohort ) - > PortfolioICReview :
rows = [ self . crypto_score_row ( member . proposal ) for member in cohort . members . select_related ( " proposal " ) ]
rows = [ self . _sol_final_ic_adjustment ( row ) for row in rows ]
rows . sort ( key = lambda row : row [ " crypto_ic_score " ] , reverse = True )
top_3 = [ row for row in rows if self . _qualifies_finalist ( row ) ] [ : 3 ]
top_ids = { row [ " proposal_id " ] for row in top_3 }
for rank , row in enumerate ( rows , start = 1 ) :
member = cohort . members . get ( proposal_id = row [ " proposal_id " ] )
member . rank = rank
member . portfolio_score = row [ " crypto_ic_score " ]
member . is_top_3 = row [ " proposal_id " ] in top_ids
member . save ( update_fields = [ " rank " , " portfolio_score " , " is_top_3 " , " updated_at " ] )
row [ " rank " ] = rank
review , _ = PortfolioICReview . objects . update_or_create ( cohort = cohort , defaults = { " rankings " : rows , " top_3 " : top_3 , " concentration " : self . _crypto_concentration ( rows ) , " metadata " : { " finalist_shortfall " : max ( 0 , 3 - len ( top_3 ) ) , " no_fund_decision_v01 " : True } } )
2026-08-16 21:00:15 +07:00
model_usage = Counter ( cohort . metrics . get ( " model_usage " , { } ) )
2026-08-16 21:56:09 +07:00
model_usage [ " sol_token_utility_judge_requests " ] = max ( model_usage . get ( " sol_token_utility_judge_requests " , 0 ) , cohort . metrics . get ( " sol_token_utility_judge_requests " , 0 ) )
2026-08-16 21:00:15 +07:00
model_usage [ " sol_final_ic_requests " ] + = len ( rows ) if self . final_ic_model_hint == " sol " else 0
model_usage [ " qwen_requests " ] + = 0
2026-08-16 21:56:09 +07:00
cohort . metrics = { * * cohort . metrics , " crypto_ranked_count " : len ( rows ) , " crypto_top_3_count " : len ( top_3 ) , " autonomous_crypto_survivors " : len ( [ row for row in rows if row . get ( " crypto_autonomy_class " ) == CryptoAutonomyClass . AUTONOMOUS_CRYPTO ] ) , " assisted_high_potential " : len ( [ row for row in rows if row . get ( " crypto_ic_decision " ) == CryptoICDecisionType . ASSISTED_CRYPTO_HIGH_POTENTIAL ] ) , " finalists " : len ( top_3 ) , " model_usage " : dict ( model_usage ) , " sol_token_utility_judge_requests " : model_usage . get ( " sol_token_utility_judge_requests " , 0 ) , " sol_final_ic_requests " : model_usage . get ( " sol_final_ic_requests " , 0 ) , " qwen_requests " : model_usage . get ( " qwen_requests " , 0 ) }
2026-08-16 18:12:50 +07:00
cohort . status = " CRYPTO_IC_COMPLETE "
cohort . save ( update_fields = [ " metrics " , " status " , " updated_at " ] )
return review
def protocol_security_gate ( self , cohort : VentureCohort ) - > dict [ str , int ] :
blocked = 0
passed = 0
for member in cohort . members . select_related ( " proposal " ) :
proposal = member . proposal
text = self . _proposal_text ( proposal )
required = [ " contract " , " oracle " , " key " , " admin " , " pause " , " treasury " ]
missing = [ item for item in required if item not in text ]
critical = any ( self . _positive_phrase_present ( text , term ) for term in [ " unaudited mainnet " , " custody user funds " , " bridge dependency " , " upgradeable without timelock " ] )
2026-08-16 19:31:15 +07:00
decision = ProtocolSecurityDecision . BLOCK_TESTNET if critical or len ( missing ) > = 5 else ProtocolSecurityDecision . REVISE_SECURITY_MODEL if len ( missing ) > = 3 else ProtocolSecurityDecision . PASS_FOR_TESTNET_DESIGN
if decision == ProtocolSecurityDecision . BLOCK_TESTNET :
2026-08-16 18:12:50 +07:00
blocked + = 1
else :
passed + = 1
2026-08-16 19:31:15 +07:00
assessment = ProtocolSecurityAssessment . objects . update_or_create ( proposal = proposal , defaults = { " decision " : decision , " threat_model " : { " contract_architecture " : " design-stage only " , " staking_slashing_logic " : " requires objective measurable failures " , " oracle_assumptions " : " must avoid circular/manual oracle dependency " , " upgradeability " : " timelock/admin controls required " , " pause_emergency_controls " : " required before testnet " , " mainnet_allowed " : False } , " missing_controls " : missing , " privileged_roles " : [ " admin " , " treasury " , " pauser " ] , " economic_attack_surfaces " : [ " sybil providers " , " collusion " , " oracle manipulation " , " slash griefing " ] , " key_management_assumptions " : [ " no production key custody in V0.2 " , " multisig/timelock required later " ] , " rationale " : " Guard-style protocol threat model review; no Solidity audit or mainnet approval. " } ) [ 0 ]
self . _artifact ( proposal , cohort . mandate , " CRYPTO_PROTOCOL_SECURITY_GATE " , f " Protocol Security Gate: { proposal . title } " , { " decision " : assessment . decision , " missing_controls " : missing , " critical_risk " : critical , " mainnet_allowed " : False } , f " { assessment . decision } . Missing controls: { ' , ' . join ( missing ) or ' none ' } . Mainnet is not allowed in V0.2. " , " crypto_guard_workflow " , graph_run = cohort . graph_run )
proposal . metadata = { * * proposal . metadata , " crypto_security_gate " : { " decision " : assessment . decision , " missing_controls " : missing , " critical_risk " : critical , " mainnet_allowed " : False } }
2026-08-16 18:12:50 +07:00
proposal . save ( update_fields = [ " metadata " , " updated_at " ] )
cohort . metrics = { * * cohort . metrics , " protocol_security_gate_blocked " : blocked , " protocol_security_gate_passed " : passed }
cohort . save ( update_fields = [ " metrics " , " updated_at " ] )
return { " blocked " : blocked , " passed " : passed }
2026-08-16 19:31:15 +07:00
def token_launch_readiness ( self , proposal : CompanyProposal ) - > TokenLaunchReadinessAssessment :
simulation = getattr ( proposal , " tokenomics_simulation " , None )
token = getattr ( proposal , " token_utility_assessment " , None ) or self . assess_token_necessity ( proposal )
security = getattr ( proposal , " protocol_security_assessment " , None )
if token . classification in { TokenNecessityClassification . TOKEN_OPTIONAL , TokenNecessityClassification . TOKEN_UNNECESSARY } :
status = TokenLaunchReadinessStatus . TOKEN_MODEL_REVISION_REQUIRED
elif security and security . decision == ProtocolSecurityDecision . BLOCK_TESTNET :
status = TokenLaunchReadinessStatus . SECURITY_REVIEW_REQUIRED
else :
status = TokenLaunchReadinessStatus . PRODUCT_TRACTION_REQUIRED
return TokenLaunchReadinessAssessment . objects . update_or_create ( proposal = proposal , defaults = { " real_users " : False , " repeat_usage " : False , " real_protocol_fees " : False , " token_necessity_validated " : False , " token_demand_loop_validated " : False , " security_audit_status " : " NOT_AUDITED_DESIGN_ONLY " , " testnet_stability " : " NOT_PROVEN " , " tokenomics_stress_tests " : simulation . summary if simulation else { } , " legal_review_status " : " LEGAL_REVIEW_REQUIRED " , " jurisdiction_policy_status " : " US_EXCLUDED_TOKEN_SALE_DISABLED " , " admin_key_controls " : " DESIGN_REQUIRED " , " treasury_controls " : " DESIGN_REQUIRED " , " decentralization_readiness " : " NOT_READY " , " launch_readiness_status " : status } ) [ 0 ]
2026-08-16 18:12:50 +07:00
def regulatory_gate ( self , cohort : VentureCohort ) - > None :
gated = 0
for member in cohort . members . select_related ( " proposal " ) :
policy = self . regulatory_policy ( member . proposal )
if policy . human_legal_gate :
gated + = 1
cohort . metrics = { * * cohort . metrics , " human_legal_gate_count " : gated , " legal_review_required " : True }
cohort . save ( update_fields = [ " metrics " , " updated_at " ] )
def capability_analysis ( self , cohort : VentureCohort ) - > list [ dict [ str , Any ] ] :
2026-08-16 19:31:15 +07:00
capabilities = [
( " Guard model " , " AVAILABLE " ) ,
( " protocol threat modelling " , " AVAILABLE " ) ,
( " Solidity implementation " , " AVAILABLE " ) ,
( " token simulation harness " , " AVAILABLE " ) ,
( " crypto research workflow " , " PARTIAL " ) ,
( " testnet deployment " , " PARTIAL " ) ,
( " wallet auth " , " MISSING " ) ,
( " key management " , " MISSING " ) ,
( " contract deployment pipeline " , " MISSING " ) ,
( " oracle/provider monitoring " , " MISSING " ) ,
( " legal review workflow " , " MISSING " ) ,
]
rows = [ { " capability " : capability , " count " : cohort . members . count ( ) , " status " : status , " earliest_stage " : " BEFORE_VALIDATION " } for capability , status in capabilities ]
2026-08-16 18:12:50 +07:00
review = getattr ( cohort , " portfolio_review " , None )
if review :
review . capability_demand = rows
review . recommended_build_priorities = rows [ : 5 ]
review . save ( update_fields = [ " capability_demand " , " recommended_build_priorities " , " updated_at " ] )
return rows
def update_crypto_thesis_registry ( self , cohort : VentureCohort ) - > list [ dict [ str , Any ] ] :
updates = [ ]
for member in cohort . members . select_related ( " proposal " ) :
proposal = member . proposal
proto = proposal . protocol_thesis
token = proposal . token_utility_assessment
name = f " CRYPTO:: { proto . protocol_category or member . metadata . get ( ' territory ' , ' OPEN ' ) } :: { proposal . title [ : 80 ] } "
registry , _ = PortfolioThesis . objects . update_or_create ( canonical_name = name , defaults = { " concise_thesis " : proto . protocol_thesis [ : 1000 ] , " category " : proto . protocol_category , " industry " : " crypto/protocol " , " icp " : proposal . target_customer [ : 1000 ] , " problem " : proposal . problem [ : 1000 ] , " offer " : proposal . proposed_solution [ : 1000 ] , " business_model " : " protocol " , " primary_channel " : " developer/community " , " ai_leverage " : 0.0 , " platformization_potential " : 0.0 , " fingerprint " : self . _fingerprint ( proposal . title + proto . protocol_thesis ) , " status " : PortfolioThesisStatus . ACTIVE_CANDIDATE , " proposal_count " : 1 , " best_ic_score " : member . portfolio_score , " best_company " : proposal , " last_seen_cohort " : cohort , " metadata " : { " venture_track " : VentureTrack . CRYPTO_PROTOCOL , " protocol_category " : proto . protocol_category , " token_utility_type " : token . utility_categories , " token_necessity " : token . classification , " regulatory_risk " : proposal . crypto_jurisdiction_policy . regulatory_manageability_score , " autonomy_score " : proposal . autonomous_assessment . autonomous_operability_score } , " venture_track " : VentureTrack . CRYPTO_PROTOCOL , " best_autonomous_operability_score " : proposal . autonomous_assessment . autonomous_operability_score } )
if registry . first_seen_cohort_id is None :
registry . first_seen_cohort = cohort
registry . save ( update_fields = [ " first_seen_cohort " , " updated_at " ] )
updates . append ( { " canonical_name " : registry . canonical_name , " token_necessity " : token . classification , " best_ic_score " : member . portfolio_score } )
cohort . metadata = { * * cohort . metadata , " crypto_thesis_registry_after " : updates }
cohort . save ( update_fields = [ " metadata " , " updated_at " ] )
return updates
def produce_crypto_cohort_report ( self , cohort : VentureCohort ) - > VentureArtifact :
review = cohort . portfolio_review
rows = review . rankings
2026-08-16 19:31:15 +07:00
research_health = self . _research_health ( rows )
2026-08-16 21:00:15 +07:00
routed_to_saas = [ { " company " : proposal . title , " token_classification " : getattr ( proposal , " token_utility_assessment " , None ) . classification if hasattr ( proposal , " token_utility_assessment " ) else None , " product_thesis " : proposal . description , " reason " : " Failed onchain/token counterfactual but may be valuable as pre-token/SaaS product. " } for proposal in cohort . mandate . company_proposals . filter ( status = CompanyProposalStatus . REJECTED , metadata__routed_to_saas = True ) . order_by ( " created_at " ) [ : 10 ] ]
2026-08-16 21:56:09 +07:00
comparison = { " v02 " : cohort . metadata . get ( " v02_baseline " , { " raw " : 30 , " crypto_survivors " : 2 , " autonomous_survivors " : 0 , " finalists " : 0 } ) , " v03 " : cohort . metadata . get ( " v03_baseline " , { } ) , " v031 " : { " raw " : cohort . metrics . get ( " raw_generated " , 0 ) , " onchain_passed " : cohort . metrics . get ( " onchain_passed " , 0 ) , " onchain_rejected " : cohort . metrics . get ( " onchain_rejected " , 0 ) , " token_strongly_justified " : cohort . metrics . get ( " token_strongly_justified " , 0 ) , " token_essential " : cohort . metrics . get ( " token_essential " , 0 ) , " crypto_survivors " : cohort . members . count ( ) , " autonomous_survivors " : cohort . metrics . get ( " autonomous_crypto_survivors " , 0 ) , " assisted_high_potential " : cohort . metrics . get ( " assisted_high_potential " , 0 ) , " finalists " : len ( review . top_3 ) , " average_research_quality " : research_health . get ( " average_coverage " , 0 ) , " idea_diversity " : review . concentration } }
security_summary = { " guard_reviews " : cohort . metrics . get ( " protocol_security_gate_passed " , 0 ) + cohort . metrics . get ( " protocol_security_gate_blocked " , 0 ) , " pass " : cohort . metrics . get ( " protocol_security_gate_passed " , 0 ) , " revise_or_pass " : cohort . metrics . get ( " protocol_security_gate_passed " , 0 ) , " block " : cohort . metrics . get ( " protocol_security_gate_blocked " , 0 ) }
content = { " title " : " CRYPTO VENTURE COHORT V0.3.1 " , " cohort_id " : cohort . cohort_id , " graph_run " : str ( cohort . graph_run_id or " " ) , " runtime " : cohort . metrics , " raw_protocols_generated " : cohort . metrics . get ( " raw_generated " , 0 ) , " raw_sol_theses " : cohort . metrics . get ( " raw_sol_theses " , 0 ) , " onchain_rejected " : cohort . metrics . get ( " onchain_rejected " , 0 ) , " onchain_passed " : cohort . metrics . get ( " onchain_passed " , 0 ) , " token_design_attempts " : cohort . metrics . get ( " token_design_attempts " , 0 ) , " token_design_skipped " : cohort . metrics . get ( " token_design_skipped_due_to_onchain_rejection " , 0 ) , " token_unnecessary " : cohort . metrics . get ( " token_unnecessary_rejections " , 0 ) , " token_optional_routed_saas " : cohort . metrics . get ( " token_optional_route_to_saas " , 0 ) , " token_strongly_justified " : cohort . metrics . get ( " token_strongly_justified " , 0 ) , " token_essential " : cohort . metrics . get ( " token_essential " , 0 ) , " duplicates " : cohort . metrics . get ( " duplicate_rejections " , 0 ) , " crypto_survivors " : cohort . members . count ( ) , " autonomous_crypto_survivors " : cohort . metrics . get ( " autonomous_crypto_survivors " , 0 ) , " assisted_high_potential " : cohort . metrics . get ( " assisted_high_potential " , 0 ) , " security_blocked " : cohort . metrics . get ( " protocol_security_gate_blocked " , 0 ) , " finalists " : len ( review . top_3 ) , " generation_attempts " : cohort . metrics . get ( " generation_attempts " , 0 ) , " model_usage " : cohort . metrics . get ( " model_usage " , { } ) , " research_summary " : research_health , " security_summary " : security_summary , " ranking " : rows , " top_3 " : review . top_3 , " routed_to_saas " : routed_to_saas , " v02_v03_v031_comparison " : comparison , " v02_comparison " : comparison , " token_red_team_failures " : cohort . metrics . get ( " token_red_team_failures " , { } ) , " token_utility_distribution " : dict ( Counter ( util for row in rows for util in row . get ( " token_utility " , [ ] ) ) ) , " crypto_thesis_saturation " : review . concentration , " capability_gaps " : review . capability_demand , " research_health " : research_health , " system_metrics " : cohort . metrics , " stop_conditions " : { " token_sale " : False , " nft_sale " : False , " founding_membership_sale " : False , " fundraising " : False , " mainnet_issuance " : False , " user_contact " : False , " real_spend " : 0 } }
artifact = self . _artifact ( None , cohort . mandate , " CRYPTO_VENTURE_COHORT_REPORT " , " Crypto Venture Cohort V0.3.1 Report " , content , self . _readable_report ( content ) , " crypto_portfolio_ic " , graph_run = cohort . graph_run )
2026-08-16 18:12:50 +07:00
cohort . status = " COMPLETE "
cohort . save ( update_fields = [ " status " , " updated_at " ] )
return artifact
2026-08-16 19:31:15 +07:00
def _research_health ( self , rows : list [ dict [ str , Any ] ] ) - > dict [ str , Any ] :
engine_counts = Counter ( )
accepted = 0
rejected = 0
2026-08-16 21:00:15 +07:00
primary = 0
avoided = 0
2026-08-16 19:31:15 +07:00
coverage = [ ]
for row in rows :
research = row . get ( " research " , { } )
accepted + = int ( research . get ( " source_count " , 0 ) or 0 )
rejected + = int ( research . get ( " source_rejection_count " , 0 ) or 0 )
2026-08-16 21:00:15 +07:00
primary + = int ( research . get ( " primary_source_count " , 0 ) or 0 )
avoided + = int ( research . get ( " queries_avoided_due_to_circuit_breaker " , 0 ) or 0 )
2026-08-16 19:31:15 +07:00
coverage . append ( float ( research . get ( " coverage_ratio " , 0 ) or 0 ) )
engine_counts . update ( research . get ( " search_engine_health " , { } ) )
2026-08-16 21:00:15 +07:00
return { " search_engines " : dict ( engine_counts ) , " sources_accepted " : accepted , " sources_rejected " : rejected , " primary_sources_accepted " : primary , " queries_avoided_due_to_circuit_breaker " : avoided , " average_coverage " : round ( sum ( coverage ) / max ( 1 , len ( coverage ) ) , 2 ) , " healthy " : engine_counts . get ( " AVAILABLE " , 0 ) , " rate_limited " : engine_counts . get ( " RATE_LIMITED " , 0 ) , " captcha " : engine_counts . get ( " CAPTCHA " , 0 ) , " denied " : engine_counts . get ( " ACCESS_DENIED " , 0 ) , " timed_out " : engine_counts . get ( " TIMEOUT " , 0 ) }
2026-08-16 19:31:15 +07:00
2026-08-16 18:12:50 +07:00
def assess_token_necessity ( self , proposal : CompanyProposal ) - > TokenUtilityAssessment :
crypto = proposal . metadata . get ( " crypto " , { } )
2026-08-16 22:46:24 +07:00
text = self . _design_text ( proposal )
2026-08-16 21:56:09 +07:00
utilities = [ u for u in crypto . get ( " token_utility " , [ ] ) if isinstance ( u , str ) ] or self . _as_list ( getattr ( proposal , " protocol_thesis " , None ) . utility_categories if hasattr ( proposal , " protocol_thesis " ) else [ ] ) or self . _infer_utilities ( text )
2026-08-16 19:31:15 +07:00
roles = self . token_role_decomposition ( proposal )
2026-08-16 21:56:09 +07:00
utility_profile = self . token_utility_profile ( proposal , roles )
2026-08-16 18:12:50 +07:00
strong_count = sum ( 1 for utility in utilities if utility . lower ( ) in ALLOWED_TOKEN_UTILITIES or any ( term in utility . lower ( ) for term in [ " stake " , " slash " , " collateral " , " fee " , " marketplace " , " attestation " , " compute " , " machine " , " security " ] ) )
2026-08-16 21:56:09 +07:00
strong_roles = [ role for role , value in roles . roles . items ( ) if value in { " REQUIRED " , " STRONGLY_USEFUL " } ]
structural_roles = [ role for role in strong_roles if role in STRUCTURAL_TOKEN_ROLES ]
required_roles = len ( strong_roles )
2026-08-16 19:31:15 +07:00
weak = any ( term in text for term in [ " meme " , " speculative " , " community token " , " marketing token " , " community marketing " , " governance token only " , " token gated subscription " ] )
2026-08-16 21:56:09 +07:00
weak_only = bool ( strong_roles ) and not structural_roles and all ( role in WEAK_TOKEN_ROLES for role in strong_roles )
payment_only = strong_roles == [ " DEMAND_SIDE_PAYMENT " ] or roles . roles . get ( " PROTOCOL_FEE_ASSET " ) in { " REQUIRED " , " STRONGLY_USEFUL " } and len ( strong_roles ) < = 1
score = min ( 100 , 35 + strong_count * 4 + len ( strong_roles ) * 8 + len ( structural_roles ) * 13 + ( 12 if " slash " in text or " slashing " in text else 0 ) + ( 8 if " provider " in text else 0 ) - ( 35 if payment_only or weak_only else 0 ) - ( 35 if weak else 0 ) - int ( utility_profile . get ( " SPECULATION_DEPENDENCE " , 0 ) * 0.25 ) )
2026-08-16 21:00:15 +07:00
economic_model = getattr ( proposal , " token_economic_model " , None )
model_payload = { " unit_of_service " : economic_model . unit_of_service , " payment_asset " : economic_model . payment_asset , " stake_requirement " : economic_model . stake_requirement , " collateral_requirement " : economic_model . collateral_requirement } if economic_model else { }
2026-08-16 23:32:55 +07:00
judge_context = { " title " : proposal . title , " product_thesis " : crypto . get ( " product_thesis " ) or proposal . description , " protocol_thesis " : crypto . get ( " protocol_thesis " ) or getattr ( proposal , " protocol_thesis " , None ) . protocol_thesis if hasattr ( proposal , " protocol_thesis " ) else " " , " token_thesis " : crypto . get ( " token_thesis " ) or proposal . pitch . get ( " Token thesis " , " " ) , " token_utility " : utilities , " token_demand_loop " : proposal . pitch . get ( " Token demand loop " , [ ] ) , " value_capture " : crypto . get ( " value_capture " , " " ) , " token_roles " : roles . roles , " utility_profile " : utility_profile , " economic_model " : model_payload }
judge_prompt = " CRYPTO_TOKEN_UTILITY_JUDGE V0.3.2B. Return strict JSON only. Required fields: token_classification TOKEN_ESSENTIAL/TOKEN_STRONGLY_JUSTIFIED/TOKEN_OPTIONAL/TOKEN_UNNECESSARY; score 0-100; utility_scores object; strong_structural_roles list; weak_roles list; counterfactual_analysis object including external_collateral_identical_security and stable_collateral_identical_security booleans; external_collateral_counterfactual non-empty object/string; material_improvements_over_USDC_ETH non-empty list; native_asset_costs_and_risks non-empty list; argument_for_native_token non-empty string; argument_against_native_token non-empty string; final_rationale non-empty string; native_token_removed_breaks non-empty list; native_token_removed_degradation NONE/MINOR/MODERATE/MATERIAL/CRITICAL; native_token_removed_explanation non-empty string. If TOKEN_OPTIONAL, final_rationale must answer why ETH/USDC/external collateral is preferable despite claimed material degradation. If TOKEN_ESSENTIAL or TOKEN_STRONGLY_JUSTIFIED, final_rationale must answer what protocol-specific property cannot be reproduced economically enough with ETH/USDC/external collateral. Do not automatically promote. Judge context: " + json . dumps ( judge_context , default = str )
2026-08-16 22:59:30 +07:00
sol_review = self . _complete_token_utility_judge ( judge_prompt , roles . roles )
2026-08-16 22:46:24 +07:00
sol_structural_roles = [ str ( role ) for role in self . _as_list ( ( sol_review or { } ) . get ( " strong_structural_roles " ) ) if str ( role ) in STRUCTURAL_TOKEN_ROLES ]
sol_scores = ( sol_review or { } ) . get ( " utility_scores " , { } ) if isinstance ( ( sol_review or { } ) . get ( " utility_scores " , { } ) , dict ) else { }
if sol_structural_roles :
structural_roles = sorted ( set ( structural_roles ) | set ( sol_structural_roles ) )
if sol_scores :
utility_profile = { * * utility_profile , * * { key : int ( float ( value ) ) for key , value in sol_scores . items ( ) if key in TOKEN_UTILITY_SCORE_KEYS } }
2026-08-16 18:12:50 +07:00
if sol_review :
score = float ( sol_review . get ( " score " , score ) )
2026-08-16 21:56:09 +07:00
sol_classification = str ( sol_review . get ( " token_classification " ) or sol_review . get ( " classification " , " " ) )
2026-08-16 18:12:50 +07:00
else :
sol_classification = " "
2026-08-16 21:56:09 +07:00
if len ( strong_roles ) > = 2 and structural_roles and score > = 85 :
2026-08-16 18:12:50 +07:00
classification = TokenNecessityClassification . TOKEN_ESSENTIAL
2026-08-16 21:56:09 +07:00
elif len ( strong_roles ) > = 2 and structural_roles and score > = 75 :
2026-08-16 18:12:50 +07:00
classification = TokenNecessityClassification . TOKEN_STRONGLY_JUSTIFIED
elif score > = 50 :
classification = TokenNecessityClassification . TOKEN_OPTIONAL
else :
classification = TokenNecessityClassification . TOKEN_UNNECESSARY
if sol_classification in TokenNecessityClassification . values :
classification = sol_classification
2026-08-16 21:56:09 +07:00
degradation = str ( ( sol_review or { } ) . get ( " native_token_removed_degradation " , " MATERIAL " if structural_roles else " MINOR " ) )
2026-08-16 22:46:24 +07:00
no_native_claim = any ( phrase in text for phrase in [ " native token not required " , " no native token required " , " no proprietary token required " ] )
has_explicit_improvement = bool ( self . _as_list ( ( sol_review or { } ) . get ( " material_improvements_over_USDC_ETH " ) ) or self . _as_list ( ( sol_review or { } ) . get ( " native_token_removed_breaks " ) ) or ( sol_review or { } ) . get ( " argument_for_native_token " ) )
2026-08-16 21:56:09 +07:00
if weak :
classification = TokenNecessityClassification . TOKEN_UNNECESSARY
score = min ( score , 35 )
2026-08-16 22:46:24 +07:00
elif no_native_claim and not has_explicit_improvement :
classification = TokenNecessityClassification . TOKEN_UNNECESSARY
score = min ( score , 35 )
2026-08-16 21:56:09 +07:00
elif payment_only or weak_only or not structural_roles :
classification = TokenNecessityClassification . TOKEN_OPTIONAL if score > = 45 else TokenNecessityClassification . TOKEN_UNNECESSARY
score = min ( score , 62 )
2026-08-16 22:46:24 +07:00
elif classification in { TokenNecessityClassification . TOKEN_ESSENTIAL , TokenNecessityClassification . TOKEN_STRONGLY_JUSTIFIED } and not has_explicit_improvement :
classification = TokenNecessityClassification . TOKEN_OPTIONAL
score = min ( score , 62 )
2026-08-16 21:56:09 +07:00
if ( len ( strong_roles ) < 2 or not structural_roles or degradation in { " NONE " , " MINOR " } ) and classification in { TokenNecessityClassification . TOKEN_ESSENTIAL , TokenNecessityClassification . TOKEN_STRONGLY_JUSTIFIED } :
2026-08-16 21:00:15 +07:00
classification = TokenNecessityClassification . TOKEN_OPTIONAL
score = min ( score , 62 )
2026-08-16 21:56:09 +07:00
proposal . metadata = { * * proposal . metadata , " crypto " : { * * crypto , " token_utility_judge_model " : self . final_ic_model_hint , " token_utility_judge_used " : bool ( sol_review ) , " token_utility_profile " : utility_profile , " strong_structural_roles " : structural_roles , " strong_token_roles " : strong_roles } }
2026-08-16 21:00:15 +07:00
proposal . save ( update_fields = [ " metadata " , " updated_at " ] )
2026-08-16 23:32:55 +07:00
return TokenUtilityAssessment . objects . update_or_create ( proposal = proposal , defaults = { " classification " : classification , " token_necessity_score " : score , " utility_categories " : utilities , " fiat_or_database_substitution " : str ( ( sol_review or { } ) . get ( " counterfactual_analysis " , " USDC/ETH/external collateral may preserve basic operation but must be compared against protocol-specific security and coordination improvements. " ) ) , " rationale " : str ( ( sol_review or { } ) . get ( " final_rationale " ) or ( sol_review or { } ) . get ( " rationale " ) or " Token score derives from structural utility, not native payment currency alone. " ) , " metadata " : { " weak_utility_terms " : INSUFFICIENT_TOKEN_UTILITIES , " sol_counterfactual_review " : sol_review or { } , " sol_token_utility_judge " : sol_review or { } , " independent_token_utility_judge " : " CRYPTO_TOKEN_UTILITY_JUDGE " , " argument_for_native_token " : ( sol_review or { } ) . get ( " argument_for_native_token " , " " ) , " argument_against_native_token " : ( sol_review or { } ) . get ( " argument_against_native_token " , " " ) , " utility_scores " : utility_profile , " strong_structural_roles " : structural_roles , " strong_token_roles " : strong_roles , " weak_roles " : ( sol_review or { } ) . get ( " weak_roles " , [ ] ) , " counterfactual_analysis " : ( sol_review or { } ) . get ( " counterfactual_analysis " , " " ) , " external_collateral_counterfactual " : ( sol_review or { } ) . get ( " external_collateral_counterfactual " , { } ) , " material_improvements_over_USDC_ETH " : self . _as_list ( ( sol_review or { } ) . get ( " material_improvements_over_USDC_ETH " ) ) , " native_asset_costs_and_risks " : self . _as_list ( ( sol_review or { } ) . get ( " native_asset_costs_and_risks " ) ) , " required_roles " : roles . required_roles , " payment_only_penalty " : payment_only , " native_token_removed_breaks " : self . _as_list ( ( sol_review or { } ) . get ( " native_token_removed_breaks " ) ) , " native_token_removed_degradation " : degradation , " native_token_removed_explanation " : ( sol_review or { } ) . get ( " native_token_removed_explanation " , " " ) , " final_rationale " : ( sol_review or { } ) . get ( " final_rationale " , " " ) } } ) [ 0 ]
2026-08-16 19:31:15 +07:00
def token_role_decomposition ( self , proposal : CompanyProposal ) - > TokenRoleDecomposition :
2026-08-16 22:46:24 +07:00
text = self . _design_text ( proposal )
2026-08-16 21:56:09 +07:00
explicit_roles = proposal . metadata . get ( " crypto " , { } ) . get ( " token_roles " , { } ) if isinstance ( proposal . metadata , dict ) else { }
2026-08-16 19:31:15 +07:00
roles = { }
role_terms = {
" SECURITY_BOND " : [ " bond " , " security budget " ] ,
" SLASHABLE_COLLATERAL " : [ " slash " , " slashing " , " collateral " ] ,
2026-08-16 21:56:09 +07:00
" PROVIDER_ADMISSION " : [ " provider admission " , " permissionless provider " , " admission " ] ,
" RESOURCE_ALLOCATION " : [ " resource allocation " , " scarce " , " quota " , " bandwidth " , " storage " , " compute slot " ] ,
" MACHINE_ECONOMIC_IDENTITY " : [ " machine economic " , " machine identity " , " agent identity " , " reputation " ] ,
" CONTRIBUTION_ACCOUNTING " : [ " contribution " , " contributor " , " accounting " ] ,
" SECURITY_BUDGET " : [ " security budget " ] ,
" PROTOCOL_FEE_ASSET " : [ " protocol fee " , " fee asset " ] ,
" PROVIDER_REWARD " : [ " provider reward " , " reward " ] ,
" DEMAND_SIDE_PAYMENT " : [ " payment " , " settlement " ] ,
2026-08-16 19:31:15 +07:00
" GOVERNANCE " : [ " governance " , " vote " ] ,
2026-08-16 21:56:09 +07:00
" ACCESS " : [ " access " ] ,
2026-08-16 19:31:15 +07:00
" TREASURY " : [ " treasury " ] ,
" OTHER " : [ ] ,
}
for role , terms in role_terms . items ( ) :
2026-08-16 21:56:09 +07:00
explicit = str ( explicit_roles . get ( role , " " ) ) . upper ( ) if isinstance ( explicit_roles , dict ) else " "
if explicit in { " REQUIRED " , " STRONGLY_USEFUL " , " USEFUL " , " OPTIONAL " , " UNNECESSARY " } :
value = explicit
elif explicit_roles :
value = TokenRoleRequirement . UNNECESSARY
2026-08-16 19:31:15 +07:00
elif role == " GOVERNANCE " and any ( term in text for term in terms ) and not any ( term in text for term in [ " parameter " , " slashing " , " treasury " ] ) :
value = TokenRoleRequirement . OPTIONAL
elif any ( term in text for term in terms ) :
2026-08-16 21:56:09 +07:00
value = " REQUIRED " if role in STRUCTURAL_TOKEN_ROLES else " USEFUL "
2026-08-16 19:31:15 +07:00
else :
value = TokenRoleRequirement . UNNECESSARY
roles [ role ] = value
2026-08-16 21:56:09 +07:00
required = [ role for role , value in roles . items ( ) if value in { " REQUIRED " , " STRONGLY_USEFUL " } ]
stablecoin = { " MODEL_A_native_payment_staking_governance " : " baseline proposal " , " MODEL_B_stablecoin_payment_native_bond " : " preferred if payment utility is separable " , " MODEL_C_stablecoin_payment_stablecoin_collateral " : " valid if slashing/collateral does not need protocol-native exposure " , " MODEL_D_onchain_no_proprietary_token " : " valid if proprietary token adds no security/resource allocation advantage " , " MODEL_E_centralized_saas_database " : " routes to SaaS if verification/settlement/reputation do not degrade " , " usdc_identical_payment_utility " : roles . get ( " DEMAND_SIDE_PAYMENT " ) not in { " REQUIRED " , " STRONGLY_USEFUL " } , " external_collateral_identical_security " : " SLASHABLE_COLLATERAL " not in required and " SECURITY_BOND " not in required , " stable_collateral_identical_security " : " SLASHABLE_COLLATERAL " not in required and " SECURITY_BOND " not in required }
2026-08-16 19:31:15 +07:00
outcome = " Native token removal materially degrades security/reputation if required roles remain. " if required else " Native token removed changes little; route to SaaS or revise token model. "
return TokenRoleDecomposition . objects . update_or_create ( proposal = proposal , defaults = { " roles " : roles , " required_roles " : required , " stablecoin_counterfactual " : stablecoin , " native_token_removed_outcome " : outcome } ) [ 0 ]
2026-08-16 21:56:09 +07:00
def token_utility_profile ( self , proposal : CompanyProposal , roles : TokenRoleDecomposition ) - > dict [ str , int ] :
2026-08-16 22:46:24 +07:00
text = self . _design_text ( proposal )
2026-08-16 21:56:09 +07:00
score = { key : 0 for key in TOKEN_UTILITY_SCORE_KEYS }
score [ " SECURITY_UTILITY " ] = 85 if roles . roles . get ( " SECURITY_BOND " ) in { " REQUIRED " , " STRONGLY_USEFUL " } else 35
score [ " COLLATERAL_UTILITY " ] = 85 if roles . roles . get ( " SLASHABLE_COLLATERAL " ) in { " REQUIRED " , " STRONGLY_USEFUL " } else 30
score [ " SLASHING_UTILITY " ] = 82 if " slash " in text and roles . roles . get ( " SLASHABLE_COLLATERAL " ) in { " REQUIRED " , " STRONGLY_USEFUL " } else 25
score [ " RESOURCE_ALLOCATION_UTILITY " ] = 82 if roles . roles . get ( " RESOURCE_ALLOCATION " ) in { " REQUIRED " , " STRONGLY_USEFUL " } else 25
score [ " MACHINE_ECONOMIC_UTILITY " ] = 84 if roles . roles . get ( " MACHINE_ECONOMIC_IDENTITY " ) in { " REQUIRED " , " STRONGLY_USEFUL " } else 25
score [ " COORDINATION_UTILITY " ] = 75 if any ( roles . roles . get ( role ) in { " REQUIRED " , " STRONGLY_USEFUL " } for role in [ " PROVIDER_ADMISSION " , " CONTRIBUTION_ACCOUNTING " , " RESOURCE_ALLOCATION " ] ) else 35
score [ " INCENTIVE_UTILITY " ] = 70 if roles . roles . get ( " PROVIDER_REWARD " ) in { " REQUIRED " , " STRONGLY_USEFUL " , " USEFUL " } else 25
score [ " NETWORK_BOOTSTRAP_UTILITY " ] = 75 if " bootstrap " in text or roles . roles . get ( " PROVIDER_ADMISSION " ) in { " REQUIRED " , " STRONGLY_USEFUL " } else 30
score [ " VALUE_CAPTURE_UTILITY " ] = 75 if " value " in text or roles . roles . get ( " PROTOCOL_FEE_ASSET " ) in { " REQUIRED " , " STRONGLY_USEFUL " , " USEFUL " } else 30
score [ " GOVERNANCE_UTILITY " ] = 45 if roles . roles . get ( " GOVERNANCE " ) in { " REQUIRED " , " STRONGLY_USEFUL " , " USEFUL " } else 10
score [ " PAYMENT_UTILITY " ] = 45 if roles . roles . get ( " DEMAND_SIDE_PAYMENT " ) in { " REQUIRED " , " STRONGLY_USEFUL " , " USEFUL " } else 10
2026-08-16 22:46:24 +07:00
score [ " SPECULATION_DEPENDENCE " ] = 70 if any ( self . _positive_phrase_present ( text , term ) for term in [ " price appreciation " , " buyback " , " yield " , " apy " , " speculat " , " token price " ] ) else 5
2026-08-16 21:56:09 +07:00
return score
2026-08-16 19:31:15 +07:00
def assess_pretoken_monetization ( self , proposal : CompanyProposal ) - > PreTokenMonetizationAssessment :
2026-08-16 22:46:24 +07:00
text = self . _design_text ( proposal )
2026-08-16 19:31:15 +07:00
mode = PreTokenMonetizationMode . STABLECOIN_USAGE_FEES if " usage " in text or " api " in text else PreTokenMonetizationMode . PAID_BETA_ACCESS if " testnet " in text else PreTokenMonetizationMode . NONE
if " membership " in text or " founding " in text :
mode = PreTokenMonetizationMode . FOUNDING_MEMBERSHIP_NFT
immediate = [ " testnet/API access " , " usage credits " , " priority queues " , " protocol analytics " ] if mode != PreTokenMonetizationMode . NONE else [ ]
score = 0 if mode == PreTokenMonetizationMode . NONE else 55 + ( 15 if " api " in text else 0 ) + ( 10 if " automated " in text or " machine " in text else 0 )
score = min ( 100 , score )
membership_policy = { " no_investment_return " : True , " no_equity " : True , " no_profit_or_revenue_share " : True , " no_guaranteed_native_token_allocation " : True , " no_appreciation_promise " : True , " useful_without_future_token " : True , " public_sale_requires_human_legal_gate " : True , " v02_sale_executed " : False }
2026-08-16 21:00:15 +07:00
customer = proposal . target_customer [ : 180 ]
product = proposal . description [ : 220 ]
payment = proposal . pricing_hypothesis or " Stripe/stablecoin usage credits "
ladder = { " 1000 " : f " Sell 10 x $100 paid beta/API-credit packages to { customer } for { product } ; fulfill with hosted testnet/API access and automated reports. " , " 5000 " : f " Sell 20 x $250 monthly usage-credit packages via { payment } ; buyers get measurable protocol simulations, SDK/API access, and evidence dashboards before any token. " , " 10000 " : f " Sell 20 x $500 subscription/service-credit plans; fulfillment is self-service onboarding, usage metering, testnet jobs, and downloadable verification evidence. " }
return PreTokenMonetizationAssessment . objects . update_or_create ( proposal = proposal , defaults = { " mode " : mode , " pre_token_monetization_potential " : score , " pre_token_business " : " Sell useful product/network access before native token issuance using fiat/stablecoin credits, paid beta, subscription, service credits, or legally reviewed membership. No native token required. " , " immediate_utility " : immediate , " revenue_ladder " : ladder , " founding_membership_policy " : membership_policy , " autonomous_fulfillment_notes " : " Prefer self-service API/testnet onboarding, automated usage metering, and docs-first support. " } ) [ 0 ]
2026-08-16 19:31:15 +07:00
def token_economic_model ( self , proposal : CompanyProposal ) - > TokenEconomicModel :
2026-08-16 22:46:24 +07:00
text = self . _design_text ( proposal )
2026-08-16 19:31:15 +07:00
token = getattr ( proposal , " token_utility_assessment " , None ) or self . assess_token_necessity ( proposal )
avg_fee = round ( 0.03 + token . token_necessity_score / 1200 + ( 0.04 if " api " in text else 0 ) , 3 )
providers = max ( 3 , 4 + len ( token . utility_categories ) * 2 )
users = max ( 25 , int ( float ( proposal . confidence ) * 220 ) )
stake = 200 + int ( token . token_necessity_score * 10 )
2026-08-16 21:00:15 +07:00
return TokenEconomicModel . objects . update_or_create ( proposal = proposal , defaults = { " unit_of_service " : " verified job/API call/attestation " , " expected_usage_frequency " : " weekly to daily machine/API usage " , " transaction_fee_model " : " Per-use stablecoin or credit fee pre-token; protocol fees may later settle through approved token design. " , " average_fee " : avg_fee , " payment_asset " : " stablecoin_or_fiat_pre_token " , " stake_requirement " : stake , " collateral_requirement " : stake , " provider_count " : providers , " demand_side_users " : users , " slash_event_assumptions " : { " baseline_rate " : 0.01 , " high_slash_rate " : 0.08 , " objective_conditions_required " : True , " conditions " : [ " missed settlement " , " invalid proof " , " fraudulent attestation " ] } , " slash_amount " : round ( stake * 0.15 , 2 ) , " emission_schedule " : { " v03 " : " none " , " post_launch_model_only " : " declining bootstrap subsidies " } , " bootstrap_subsidies " : 0.0 , " treasury_share " : 0.2 , " provider_reward_share " : 0.8 , " token_sinks " : [ " provider bonds " , " slashing penalties " , " protocol fees " , " security budget " ] , " unlock_assumptions " : { " v03 " : " none " } , " circulation_assumptions " : { " v03_native_token_supply " : 0 } , " metadata " : { " buyer " : proposal . target_customer , " provider " : " permissionless providers/operators serving the unit of service " , " average_transaction " : avg_fee , " protocol_fee " : round ( avg_fee * 0.2 , 3 ) , " provider_reward " : round ( avg_fee * 0.8 , 3 ) , " token_sources " : [ " earned service fees " , " bond acquisition only after legal gate " ] , " provider_economics " : { " gross_fee_share " : 0.8 , " slash_risk " : 0.01 , " stake_requirement " : stake } } } ) [ 0 ]
2026-08-16 18:12:50 +07:00
def _create_proposal ( self , mandate : CompanyMandate , payload : dict [ str , Any ] , source : str , territory : str ) - > CompanyProposal :
title = str ( payload . get ( " name " ) or payload . get ( " title " ) or f " Protocol { territory . title ( ) } " ) [ : 255 ]
product = str ( payload . get ( " product_thesis " ) or payload . get ( " product " ) or " A useful crypto-native network service. " )
protocol = str ( payload . get ( " protocol_thesis " ) or payload . get ( " protocol " ) or " Onchain settlement coordinates independent providers and users. " )
token = str ( payload . get ( " token_thesis " ) or payload . get ( " why_token " ) or " A native token bonds providers, pays protocol fees, and funds security. " )
demand_loop = self . _as_list ( payload . get ( " token_demand_loop " ) or [ " users consume service " , " users pay protocol fees " , " providers stake token " , " bad providers are slashed " , " usage-linked fees sustain rewards " ] )
validation = str ( payload . get ( " validation_experiment " ) or " Run a testnet/local-chain pilot with fake credits and simulated token accounting; no sale, fundraising, or mainnet issuance. " )
thesis = VentureThesis . objects . create ( mandate = mandate , title = title , thesis = protocol , similarity_fingerprint = self . _fingerprint ( title + protocol ) , metadata = { " source " : source , " venture_track " : VentureTrack . CRYPTO_PROTOCOL , " territory " : territory } , evidence_tier = " TIER_0_THESIS " )
2026-08-16 18:18:15 +07:00
proposal = CompanyProposal . objects . create ( mandate = mandate , thesis = thesis , title = title , description = product , problem = str ( payload . get ( " user_pain " ) or payload . get ( " problem " ) or " Users lack trustworthy decentralized coordination. " ) , target_customer = str ( payload . get ( " user " ) or payload . get ( " target_user " ) or " Developers and network participants " ) , proposed_solution = str ( payload . get ( " product " ) or product ) , business_model = str ( payload . get ( " business_model " ) or " Protocol fees on real usage; no V0 token sale. " ) , pricing_hypothesis = str ( payload . get ( " fee_model " ) or " Testnet/free validation, later usage fees. " ) , acquisition_strategy = str ( payload . get ( " bootstrap_plan " ) or " Developer adoption through testnet docs and public artifacts only after approval. " ) , validation_plan = validation , capital_requested = Decimal ( " 0 " ) , time_to_first_dollar_estimate = " No V0 revenue target; validate protocol usage without token sale. " , expected_margin = " Protocol fee margin depends on provider economics. " , build_complexity = str ( payload . get ( " build_complexity " ) or " MEDIUM-HIGH " ) , market_evidence = [ ] , differentiation = str ( payload . get ( " differentiation " ) or protocol ) , major_risks = self . _as_list ( payload . get ( " major_risks " ) or [ " Token not required " , " Regulatory uncertainty " , " Security model weak " ] ) , confidence = self . _confidence ( payload . get ( " confidence " , 0.55 ) ) , status = CompanyProposalStatus . SUBMITTED , pitch = { " Company name " : title , " One-line thesis " : str ( payload . get ( " one_line_thesis " ) or protocol ) , " Product thesis " : product , " Protocol thesis " : protocol , " Token thesis " : token , " Token demand loop " : demand_loop , " Validation experiment " : validation } , metadata = { " generation_source " : source , " venture_track " : VentureTrack . CRYPTO_PROTOCOL , " crypto " : { " territory " : territory , " product_thesis " : product , " protocol_thesis " : protocol , " token_thesis " : token , " token_demand_loop " : demand_loop , " token_utility " : self . _as_list ( payload . get ( " token_utility " ) or self . _infer_utilities ( token + " " + protocol ) ) , " value_capture " : str ( payload . get ( " value_capture " ) or " Usage fees accrue to providers, security budget, and protocol treasury. " ) , " network_effect " : str ( payload . get ( " network_effect " ) or " More users attract more providers, improving liquidity/reliability. " ) , " bootstrap_plan " : str ( payload . get ( " bootstrap_plan " ) or " Run without a live token using test credits and provider simulations. " ) , " security_model " : str ( payload . get ( " security_model " ) or " Contracts, staking, slashing, oracle controls, admin keys, and treasury controls require review. " ) , " regulatory_policy " : " US_EXCLUDED; TOKEN_SALE_DISABLED; MAINNET_TOKEN_ISSUANCE_DISABLED; FUNDRAISING_DISABLED " } , " real_spend " : 0 , " real_customer_outreach " : False , " token_sale " : False , " mainnet_issuance " : False } , evidence_tier = " TIER_0_THESIS " )
2026-08-16 21:00:15 +07:00
if payload . get ( " generation_passes " ) :
proposal . metadata = { * * proposal . metadata , " crypto " : { * * proposal . metadata [ " crypto " ] , " generation_passes " : payload . get ( " generation_passes " , { } ) , " problem_first_pass_a_had_no_token " : True , " pre_token_product " : payload . get ( " pre_token_product " ) , " pre_token_customer " : payload . get ( " pre_token_customer " ) , " pre_token_value " : payload . get ( " pre_token_value " ) , " pre_token_payment_method " : payload . get ( " pre_token_payment_method " ) , " pre_token_revenue_model " : payload . get ( " pre_token_revenue_model " ) } }
proposal . save ( update_fields = [ " metadata " , " updated_at " ] )
2026-08-16 21:56:09 +07:00
if payload . get ( " token_roles " ) :
proposal . metadata = { * * proposal . metadata , " crypto " : { * * proposal . metadata [ " crypto " ] , " token_roles " : payload . get ( " token_roles " , { } ) } }
proposal . save ( update_fields = [ " metadata " , " updated_at " ] )
2026-08-16 18:12:50 +07:00
ProtocolThesis . objects . create ( proposal = proposal , product_thesis = product , protocol_thesis = protocol , token_thesis = token , network_effect = proposal . metadata [ " crypto " ] [ " network_effect " ] , bootstrap_plan = proposal . metadata [ " crypto " ] [ " bootstrap_plan " ] , autonomous_operability = " Artifex can build/testnet deploy/monitor only; mainnet and issuance stop at human legal gate. " , utility_categories = proposal . metadata [ " crypto " ] [ " token_utility " ] , protocol_category = territory )
TokenDemandLoop . objects . create ( proposal = proposal , loop = demand_loop , real_usage_driver = str ( payload . get ( " real_usage_driver " ) or product ) , non_speculative_demand = not any ( term in " " . join ( demand_loop ) . lower ( ) for term in [ " speculation " , " price go up " ] ) , bootstrap_without_token = proposal . metadata [ " crypto " ] [ " bootstrap_plan " ] )
self . bus . publish ( " CRYPTO_PROTOCOL_PROPOSED " , payload = { " proposal_id " : str ( proposal . id ) , " territory " : territory , " source " : source } )
return proposal
2026-08-16 21:00:15 +07:00
def _protocol_payload ( self , index : int , territory : str ) - > tuple [ dict [ str , Any ] , str , Counter ] :
usage = Counter ( )
2026-08-16 18:12:50 +07:00
if self . router is not None :
try :
2026-08-16 21:00:15 +07:00
pass_a_prompt = " PASS A - PROBLEM / NETWORK DESIGN. Generate exactly one protocol venture problem thesis as JSON with NO token fields and no token design. Include name, one_line_thesis, product_thesis, user, participants, supply_side, demand_side, coordination_failure, trust_problem, why_neutral_network_may_help, pre_token_product, pre_token_customer, pre_token_value, pre_token_payment_method, pre_token_revenue_model, revenue_1000_path, revenue_5000_path, revenue_10000_path, autonomous_operating_loop, bootstrap_plan, validation_experiment, major_risks, confidence. Do not include token_thesis, token_utility, tokenomics, governance token, rewards token, or staking token. Territory: " + territory + " . Exclude API Reliability Slashing Pool, VeriMesh, VeriChain, and simple staking/slashing agent marketplaces unless the core coordination mechanism is materially different. "
pass_a = self . _model_json ( self . generation_model_hint , pass_a_prompt , purpose = ModelCapability . PLANNING )
usage [ " sol_generation_requests " if self . generation_model_hint == " sol " else " qwen_requests " ] + = 1
if pass_a and not any ( key in pass_a for key in [ " token_thesis " , " token_utility " , " tokenomics " ] ) :
pass_b_prompt = " PASS B - ONCHAIN NECESSITY. Independently evaluate whether this coordination system materially improves when implemented onchain. Return JSON with onchain_necessity_score 0-100, why_onchain, offchain_substitute, pass_onchain boolean, reasons list. Consider trust minimization, neutral settlement, permissionless participation, verifiable state, escrow, programmable guarantees, censorship resistance, cross-organization coordination, and machine-to-machine interaction. Thesis: " + json . dumps ( pass_a , default = str )
pass_b = self . _model_json ( self . generation_model_hint , pass_b_prompt , purpose = ModelCapability . REASONING )
usage [ " sol_onchain_judge_requests " if self . generation_model_hint == " sol " else " qwen_requests " ] + = 1
2026-08-16 21:56:09 +07:00
payload = { * * pass_a , * * pass_b , " token_thesis " : " Native token not assessed yet; token utility design runs only after onchain qualification. " , " token_utility " : [ ] , " token_demand_loop " : [ ] , " user_pain " : pass_a . get ( " coordination_failure " ) or pass_a . get ( " trust_problem " ) , " protocol_thesis " : pass_a . get ( " why_neutral_network_may_help " ) or pass_a . get ( " product_thesis " ) , " business_model " : pass_a . get ( " pre_token_revenue_model " ) , " fee_model " : pass_a . get ( " pre_token_payment_method " ) , " generation_passes " : { " pass_a_problem_network " : pass_a , " pass_b_onchain " : pass_b } }
2026-08-16 21:00:15 +07:00
return payload , self . generation_model_hint , usage
2026-08-16 18:12:50 +07:00
except Exception :
pass
2026-08-16 21:00:15 +07:00
usage [ " fallback_count " ] + = 1
return self . _fallback_payload ( index , territory ) , " deterministic_crypto_fallback " , usage
2026-08-16 18:12:50 +07:00
def _fallback_payload ( self , index : int , territory : str ) - > dict [ str , Any ] :
names = {
" DECENTRALIZED_AI_COMPUTE " : " Verifiable Inference Provider Market " ,
" AGENT_TO_AGENT_PAYMENTS " : " Agent Micropayment Settlement Rail " ,
" PROOF_ATTESTATION_MARKETS " : " Model Output Attestation Market " ,
" DECENTRALIZED_DATA_MARKETS " : " Consent-Bound Data License Exchange " ,
" SECURITY_STAKING_PROTOCOLS " : " API Reliability Slashing Pool " ,
}
name = names . get ( territory , f " { territory . replace ( ' _ ' , ' ' ) . title ( ) } Protocol " )
return { " name " : name , " one_line_thesis " : f " { name } coordinates independent supply and demand with staking, slashing, and usage fees. " , " product_thesis " : " A testnet marketplace/API where users request measurable digital work and providers compete to fulfill it. " , " user " : " Developers, agents, and protocol operators needing verifiable digital services. " , " protocol_thesis " : " Onchain settlement, escrow, provider bonds, attestations, and slashing coordinate parties that do not share an operator. " , " why_onchain " : " Trust-minimized escrow, programmable slashing, public reputation, and machine-to-machine settlement materially degrade if replaced by a private database. " , " token_thesis " : " The token is staked by providers, slashed for measurable failures, used for protocol fee settlement, and funds the security budget. " , " token_utility " : [ " protocol fee settlement " , " staking tied to measurable service quality " , " slashing / economic guarantees " , " decentralized marketplace coordination " ] , " token_demand_loop " : [ " users request measurable service " , " users pay protocol fee " , " providers stake token to serve " , " bad providers are slashed " , " fees reward reliable providers and security budget " , " more real usage increases fee demand " ] , " value_capture " : " Usage fees and slashing penalties accrue to reliable providers, insurance/security pool, and protocol treasury. " , " network_effect " : " More users create more jobs; more staked providers improve reliability and lower latency; more attestations improve reputation quality. " , " bootstrap_plan " : " Validate on local/testnet with fake credits and recruited simulated providers; no token sale or mainnet issuance. " , " validation_experiment " : " Run 50 simulated jobs on testnet/local chain, measure provider quality, slashing events, completion cost, and developer API reuse. " , " security_model " : " Escrow contracts, staking/slashing, oracle/attestation checks, admin key limits, pause controls, and treasury multisig require review. " , " major_risks " : [ " Token may be optional " , " Provider supply bootstrapping " , " Smart contract risk " , " Regulatory uncertainty " ] , " confidence " : 0.58 + ( index % 3 ) * 0.04 }
def _update_protocol_research_flags ( self , proposal : CompanyProposal ) - > None :
research = proposal . metadata . get ( " research " , { } )
crypto = proposal . metadata . get ( " crypto " , { } )
2026-08-16 21:00:15 +07:00
proposal . metadata = { * * proposal . metadata , " crypto " : { * * crypto , " research_status " : " RESEARCH_INSUFFICIENT " if research . get ( " source_count " , 0 ) == 0 else " SOURCE_LINKED " , " research_categories " : CRYPTO_RESEARCH_CATEGORIES } }
2026-08-16 18:12:50 +07:00
proposal . save ( update_fields = [ " metadata " , " updated_at " ] )
def red_team_proposal ( self , proposal : CompanyProposal ) - > CryptoRedTeamAssessment :
token = proposal . token_utility_assessment
onchain = self . onchain_assessment ( proposal )
value = self . value_capture_assessment ( proposal )
policy = self . regulatory_policy ( proposal )
2026-08-16 19:31:15 +07:00
roles = self . token_role_decomposition ( proposal )
2026-08-16 18:12:50 +07:00
flags = [ ]
if token . classification in { TokenNecessityClassification . TOKEN_OPTIONAL , TokenNecessityClassification . TOKEN_UNNECESSARY } :
2026-08-16 21:56:09 +07:00
flags . append ( " TOKEN_NOT_REQUIRED " )
2026-08-16 18:12:50 +07:00
if onchain . onchain_necessity_score < 70 :
2026-08-16 21:56:09 +07:00
flags . append ( " REJECT_ONCHAIN_NOT_NEEDED " )
2026-08-16 18:12:50 +07:00
if value . value_accrual_quality_score < 65 :
2026-08-16 21:56:09 +07:00
flags . append ( " VALUE_CAPTURE_WEAK " )
2026-08-16 18:12:50 +07:00
if value . tokenomics_sustainability_score < 65 :
2026-08-16 21:56:09 +07:00
flags . append ( " UNSUSTAINABLE_EMISSIONS " )
2026-08-16 18:12:50 +07:00
if policy . regulatory_manageability_score < 55 :
2026-08-16 21:56:09 +07:00
flags . append ( " LEGAL_COMPLEXITY_OUTWEIGHS_UTILITY " )
2026-08-16 22:46:24 +07:00
text = self . _design_text ( proposal )
2026-08-16 18:12:50 +07:00
if " speculat " in text or " apy " in text or " yield farm " in text :
2026-08-16 21:56:09 +07:00
flags . append ( " SPECULATION_DEPENDENT " )
2026-08-16 18:12:50 +07:00
if " governance " in text and " slash " not in text and " fee " not in text :
2026-08-16 21:56:09 +07:00
flags . append ( " GOVERNANCE_ONLY_TOKEN " )
2026-08-16 19:31:15 +07:00
if len ( [ role for role , value in roles . roles . items ( ) if value in { TokenRoleRequirement . REQUIRED , TokenRoleRequirement . USEFUL } ] ) > = 6 :
2026-08-16 21:56:09 +07:00
flags . append ( " TOKEN_DOES_TOO_MUCH " )
if roles . roles . get ( " DEMAND_SIDE_PAYMENT " ) in { " USEFUL " , " OPTIONAL " , " REQUIRED " , " STRONGLY_USEFUL " } and not any ( roles . roles . get ( role ) in { " REQUIRED " , " STRONGLY_USEFUL " } for role in STRUCTURAL_TOKEN_ROLES ) :
flags . append ( " PAYMENT_ONLY_TOKEN " )
flags . append ( " NATIVE_PAYMENT_NOT_REQUIRED " )
2026-08-16 19:31:15 +07:00
if roles . stablecoin_counterfactual . get ( " stable_collateral_identical_security " ) :
2026-08-16 21:56:09 +07:00
flags . append ( " COLLATERAL_UTILITY_WEAK " )
2026-08-16 19:31:15 +07:00
if any ( term in text for term in [ " buyback " , " revenue share " , " profit share " ] ) :
2026-08-16 21:56:09 +07:00
flags . append ( " REVENUE_CLAIM_LANGUAGE " )
2026-08-16 19:31:15 +07:00
if " buyback " in text :
2026-08-16 21:56:09 +07:00
flags . append ( " BUYBACK_DEPENDENCY " )
2026-08-16 19:31:15 +07:00
if " yield " in text or " apy " in text :
2026-08-16 21:56:09 +07:00
flags . append ( " YIELD_DEPENDENCY " )
2026-08-16 19:31:15 +07:00
if " manual dispute " in text or " human court " in text :
2026-08-16 21:56:09 +07:00
flags . append ( " SLASHING_DEPENDS_ON_HUMAN_JUDGMENT " )
2026-08-16 19:31:15 +07:00
if " central operator " in text :
2026-08-16 21:56:09 +07:00
flags . append ( " CENTRAL_OPERATOR_CONTRADICTION " )
2026-08-16 19:31:15 +07:00
if " subjective " in text and " slashing " in text :
2026-08-16 21:56:09 +07:00
flags . append ( " SLASHING_NOT_OBJECTIVE " )
sol_review = self . _sol_json ( " Independent Token Red Team V0.3.1. Return JSON with flags list using only TOKEN_DOES_TOO_MUCH, PAYMENT_ONLY_TOKEN, GOVERNANCE_ONLY_TOKEN, REWARD_ONLY_TOKEN, NATIVE_PAYMENT_NOT_REQUIRED, COLLATERAL_UTILITY_WEAK, SLASHING_NOT_OBJECTIVE, SLASHING_DEPENDS_ON_HUMAN_JUDGMENT, TOKEN_SECURITY_NOT_LINKED_TO_PROTOCOL_RISK, SPECULATION_DEPENDENT, REVENUE_CLAIM_LANGUAGE, BUYBACK_DEPENDENCY, YIELD_DEPENDENCY, UNSUSTAINABLE_EMISSIONS, MERCENARY_PROVIDER_INCENTIVES, RESOURCE_ALLOCATION_ARTIFICIAL, MACHINE_IDENTITY_NOT_PORTABLE, VALUE_CAPTURE_WEAK, BOOTSTRAP_REQUIRES_TOKEN_PRICE_GROWTH, CENTRAL_OPERATOR_CONTRADICTION, LEGAL_COMPLEXITY_OUTWEIGHS_UTILITY; severity LOW/MEDIUM/HIGH; critique. Proposal: " + json . dumps ( self . crypto_score_context ( proposal ) , default = str ) )
2026-08-16 18:12:50 +07:00
if sol_review :
for flag in self . _as_list ( sol_review . get ( " flags " ) ) :
2026-08-16 21:56:09 +07:00
flags . append ( str ( flag ) )
2026-08-16 18:12:50 +07:00
severity = " HIGH " if len ( flags ) > = 3 else " MEDIUM " if flags else " LOW "
if sol_review and str ( sol_review . get ( " severity " , " " ) ) in { " LOW " , " MEDIUM " , " HIGH " } :
severity = str ( sol_review [ " severity " ] )
deduped_flags = list ( dict . fromkeys ( str ( flag ) for flag in flags ) )
return CryptoRedTeamAssessment . objects . update_or_create ( proposal = proposal , defaults = { " flags " : deduped_flags , " severity " : severity , " critique " : str ( ( sol_review or { } ) . get ( " critique " , " Independent token red team checked token necessity, speculation dependence, value capture, emissions, governance theater, onchain necessity, and regulatory risk. " ) ) , " independent_from_generation " : True , " metadata " : { " sol_red_team_review " : sol_review or { } } } ) [ 0 ]
def crypto_score_context ( self , proposal : CompanyProposal ) - > dict [ str , Any ] :
return { " title " : proposal . title , " pitch " : proposal . pitch , " crypto " : proposal . metadata . get ( " crypto " , { } ) , " token " : getattr ( proposal , " token_utility_assessment " , None ) . classification if hasattr ( proposal , " token_utility_assessment " ) else None }
def onchain_assessment ( self , proposal : CompanyProposal ) - > OnchainNecessityAssessment :
text = self . _proposal_text ( proposal )
terms = [ " escrow " , " slashing " , " stake " , " attestation " , " settlement " , " collateral " , " trust " , " reputation " , " marketplace " , " machine " ]
score = min ( 100 , 35 + sum ( 8 for term in terms if term in text ) )
2026-08-16 21:00:15 +07:00
generation_passes = proposal . metadata . get ( " crypto " , { } ) . get ( " generation_passes " , { } )
pass_b = generation_passes . get ( " pass_b_onchain " , { } ) if isinstance ( generation_passes , dict ) else { }
if pass_b :
score = float ( pass_b . get ( " onchain_necessity_score " , score ) )
return OnchainNecessityAssessment . objects . update_or_create ( proposal = proposal , defaults = { " onchain_necessity_score " : score , " reasons " : self . _as_list ( pass_b . get ( " reasons " ) ) or [ term for term in terms if term in text ] , " offchain_substitute " : str ( pass_b . get ( " offchain_substitute " ) or " Private SaaS/database is acceptable only if escrow, slashing, public reputation, and neutral settlement are not material. " ) , " rationale " : str ( pass_b . get ( " why_onchain " ) or " Scores onchain necessity from trust-minimized coordination, settlement, staking/slashing, attestations, and multi-party neutrality. " ) , " metadata " : { " generation_pass_b " : pass_b } } ) [ 0 ]
2026-08-16 18:12:50 +07:00
def value_capture_assessment ( self , proposal : CompanyProposal ) - > ProtocolValueCapture :
text = self . _proposal_text ( proposal )
fee = " fee " in text
stake = " stake " in text or " staking " in text
slash = " slash " in text or " slashing " in text
emission_bad = any ( term in text for term in [ " high apy " , " ponzi " , " yield farm " , " emissions only " ] )
value_score = min ( 100 , 40 + ( 18 if fee else 0 ) + ( 14 if stake else 0 ) + ( 14 if slash else 0 ) + ( 10 if " treasury " in text or " security budget " in text else 0 ) )
sustainability = max ( 0 , min ( 100 , value_score - ( 35 if emission_bad else 0 ) + ( 8 if " usage " in text else 0 ) ) )
return ProtocolValueCapture . objects . update_or_create ( proposal = proposal , defaults = { " value_accrual_quality_score " : value_score , " tokenomics_sustainability_score " : sustainability , " value_accrual " : proposal . metadata . get ( " crypto " , { } ) . get ( " value_capture " , " Usage-linked fees are required. " ) , " sinks " : [ " protocol fees " , " staking bonds " , " slashing penalties " , " security budget " ] , " emissions_policy " : " No high APY. Rewards must be covered by real fees after subsidies decline. " , " sustainability_rationale " : " High emissions without real fee demand score poorly; usage-linked fees, staking, slashing, and sinks score better. " } ) [ 0 ]
def regulatory_policy ( self , proposal : CompanyProposal ) - > CryptoJurisdictionPolicy :
text = self . _proposal_text ( proposal )
issuance_risk = any ( self . _positive_phrase_present ( text , term ) for term in [ " token sale " , " public sale " , " airdrop " , " mainnet issuance " , " fundraise " , " fundraising " ] )
score = 55 if issuance_risk else 72
return CryptoJurisdictionPolicy . objects . update_or_create ( proposal = proposal , defaults = { " excluded_jurisdictions " : [ " US " ] , " excluded_person_classes " : [ " US persons " , " sanctioned persons " , " restricted jurisdictions " ] , " marketing_restrictions " : [ " No U.S.-targeted activity " , " No investment marketing " , " No yield/APY promises " ] , " sale_restrictions " : [ " TOKEN_SALE_DISABLED " , " MAINNET_TOKEN_ISSUANCE_DISABLED " , " FUNDRAISING_DISABLED " ] , " kyc_aml_requirement_status " : " REQUIRES_LEGAL_REVIEW_BEFORE_ANY_TRANSFER_OR_SALE " , " transfer_restriction_requirement_status " : " UNDETERMINED_REQUIRES_COUNSEL " , " legal_review_required " : True , " regulatory_manageability_score " : score , " jurisdiction_uncertainty " : [ " Blocking the USA does not remove all legal obligations " , " Token transfer and marketing treatment requires counsel " ] , " human_legal_gate " : True , " metadata " : { " US_EXCLUDED " : True , " TOKEN_SALE_DISABLED " : True , " MAINNET_TOKEN_ISSUANCE_DISABLED " : True , " FUNDRAISING_DISABLED " : True } } ) [ 0 ]
def simulate_tokenomics ( self , proposal : CompanyProposal ) - > TokenomicsSimulation :
scenarios = { }
2026-08-16 19:31:15 +07:00
model = getattr ( proposal , " token_economic_model " , None ) or self . token_economic_model ( proposal )
roles = getattr ( proposal , " token_role_decomposition " , None ) or self . token_role_decomposition ( proposal )
base_users = max ( 1 , model . demand_side_users )
tx_per_user = 10
2026-08-16 21:56:09 +07:00
scenario_multipliers = { " LOW_USAGE " : 0.3 , " EXPECTED_USAGE " : 1.0 , " HIGH_USAGE " : 3.0 , " NO_SUBSIDY " : 0.9 , " TOKEN_PRICE_DOWN_80 " : 0.8 , " TOKEN_PRICE_UP_10X " : 1.2 , " PROVIDER_CHURN_50 " : 0.7 , " USER_GROWTH_10X " : 10.0 , " HIGH_SLASH_RATE " : 1.0 , " ZERO_EMISSIONS " : 1.0 , " STABLECOIN_PAYMENT " : 1.0 , " ETH_COLLATERAL " : 1.0 , " USDC_COLLATERAL " : 1.0 , " NATIVE_TOKEN_REMOVED " : 1.0 }
2026-08-16 19:31:15 +07:00
for name , multiplier in scenario_multipliers . items ( ) :
2026-08-16 18:12:50 +07:00
users = int ( base_users * multiplier )
tx = int ( users * tx_per_user )
2026-08-16 19:31:15 +07:00
fees = round ( tx * model . average_fee , 2 )
provider_supply = max ( 1 , int ( model . provider_count * multiplier ) )
staking = provider_supply * model . stake_requirement
slash_rate = float ( model . slash_event_assumptions . get ( " high_slash_rate " if name == " HIGH_SLASH_RATE " else " baseline_rate " , 0.01 ) )
2026-08-16 21:00:15 +07:00
emissions = 0 if name in { " NO_SUBSIDY " , " ZERO_EMISSIONS " } else round ( max ( 0 , tx * 0.01 ) , 2 )
if name == " PROVIDER_CHURN_50 " :
2026-08-16 18:12:50 +07:00
provider_supply = max ( 1 , int ( provider_supply * 0.45 ) )
staking = max ( 100 , int ( staking * 0.45 ) )
2026-08-16 19:31:15 +07:00
native_removed = name == " NATIVE_TOKEN_REMOVED "
2026-08-16 21:56:09 +07:00
stablecoin_substitute = name in { " STABLECOIN_PAYMENT " , " ETH_COLLATERAL " , " USDC_COLLATERAL " }
degradation_dimensions = { " SECURITY_DEGRADATION " : " SECURITY_BOND " in roles . required_roles or " SLASHABLE_COLLATERAL " in roles . required_roles , " COORDINATION_DEGRADATION " : " PROVIDER_ADMISSION " in roles . required_roles , " RESOURCE_ALLOCATION_DEGRADATION " : " RESOURCE_ALLOCATION " in roles . required_roles , " BOOTSTRAP_DEGRADATION " : " DECENTRALIZED_SUPPLY_COORDINATION " in roles . required_roles , " VALUE_CAPTURE_DEGRADATION " : " PROTOCOL_FEE_ASSET " in roles . required_roles , " NETWORK_EFFECT_DEGRADATION " : bool ( roles . required_roles ) , " MACHINE_ECONOMIC_DEGRADATION " : " MACHINE_ECONOMIC_IDENTITY " in roles . required_roles }
protocol_degrades = native_removed and any ( degradation_dimensions . values ( ) )
scenarios [ name ] = { " users " : users , " transactions " : tx , " fees " : fees , " token_demand " : 0 if native_removed else fees + staking * 0.01 , " provider_supply " : provider_supply , " staking " : 0 if native_removed else staking , " emissions " : emissions , " treasury " : round ( 1000 + fees * model . treasury_share - emissions * 0.1 , 2 ) , " circulating_supply " : 0 if native_removed else 1_000_000 + emissions , " token_velocity " : 0 if native_removed else round ( tx / max ( 1 , fees + staking * 0.01 ) , 2 ) , " reward_coverage " : round ( fees / max ( 1 , emissions ) , 2 ) , " network_security_budget " : 0 if native_removed else staking , " slash_events " : round ( tx * slash_rate , 2 ) , " stablecoin_payment_works " : stablecoin_substitute or roles . roles . get ( " DEMAND_SIDE_PAYMENT " ) not in { " REQUIRED " , " STRONGLY_USEFUL " } , " external_collateral_works " : name in { " ETH_COLLATERAL " , " USDC_COLLATERAL " } and roles . stablecoin_counterfactual . get ( " external_collateral_identical_security " ) , " protocol_degrades_without_native_token " : protocol_degrades , " native_token_removed_degradation_dimensions " : degradation_dimensions if native_removed else { } }
summary = { " token_price_appreciation_primary_success_variable " : False , " subsidy_removed_survives " : scenarios [ " NO_SUBSIDY " ] [ " reward_coverage " ] > = 1.0 , " native_token_removed_degrades_protocol " : scenarios [ " NATIVE_TOKEN_REMOVED " ] [ " protocol_degrades_without_native_token " ] , " native_token_removed_degradation_dimensions " : scenarios [ " NATIVE_TOKEN_REMOVED " ] [ " native_token_removed_degradation_dimensions " ] , " stablecoin_payment_substitute_works " : scenarios [ " STABLECOIN_PAYMENT " ] [ " stablecoin_payment_works " ] , " eth_collateral_substitute_works " : scenarios [ " ETH_COLLATERAL " ] [ " external_collateral_works " ] , " usdc_collateral_substitute_works " : scenarios [ " USDC_COLLATERAL " ] [ " external_collateral_works " ] , " stress_notes " : [ " Price appreciation is not a success variable. " , " Native-token-removed asks whether protocol becomes materially worse, not literally impossible. " ] }
2026-08-16 18:12:50 +07:00
return TokenomicsSimulation . objects . update_or_create ( proposal = proposal , defaults = { " scenarios " : scenarios , " summary " : summary } ) [ 0 ]
def crypto_scenario_lab ( self , cohort : VentureCohort ) - > list [ CryptoScenarioLab ] :
labs = [ ]
for member in cohort . members . select_related ( " proposal " ) :
scenarios = [ { " scenario " : name , " expected_failure_mode " : " Must be mitigated before any mainnet deployment. " , " route_to_progeny " : name in { " smart contract exploit scenario " , " oracle failure " , " governance capture " } } for name in CRYPTO_SCENARIOS ]
labs . append ( CryptoScenarioLab . objects . update_or_create ( proposal = member . proposal , defaults = { " scenarios " : scenarios , " systemic_findings " : [ " No V0.1 mainnet deployment " , " Audit/key-management/legal gates required " ] , " progeny_candidates " : [ s [ " scenario " ] for s in scenarios if s [ " route_to_progeny " ] ] } ) [ 0 ] )
return labs
def crypto_score_row ( self , proposal : CompanyProposal ) - > dict [ str , Any ] :
2026-08-16 23:32:55 +07:00
token = getattr ( proposal , " token_utility_assessment " , None ) or self . assess_token_necessity ( proposal )
2026-08-16 18:12:50 +07:00
onchain = self . onchain_assessment ( proposal )
value = self . value_capture_assessment ( proposal )
policy = self . regulatory_policy ( proposal )
red = getattr ( proposal , " crypto_red_team " , None ) or self . red_team_proposal ( proposal )
sim = getattr ( proposal , " tokenomics_simulation " , None ) or self . simulate_tokenomics ( proposal )
2026-08-16 19:31:15 +07:00
pretoken = getattr ( proposal , " pretoken_monetization " , None ) or self . assess_pretoken_monetization ( proposal )
roles = getattr ( proposal , " token_role_decomposition " , None ) or self . token_role_decomposition ( proposal )
security = getattr ( proposal , " protocol_security_assessment " , None )
2026-08-16 18:12:50 +07:00
autonomy = self . assess_autonomy ( proposal )
2026-08-16 21:56:09 +07:00
utility_profile = token . metadata . get ( " utility_scores " , proposal . metadata . get ( " crypto " , { } ) . get ( " token_utility_profile " , { } ) ) if isinstance ( token . metadata , dict ) else { }
2026-08-16 18:12:50 +07:00
text = self . _proposal_text ( proposal )
component_scores = {
" TOKEN_NECESSITY " : token . token_necessity_score ,
" REAL_USAGE_DEMAND " : min ( 100 , 45 + ( 15 if " usage " in text else 0 ) + ( 10 if " users " in text else 0 ) + ( 10 if proposal . metadata . get ( " research " , { } ) . get ( " source_count " , 0 ) else 0 ) ) ,
" ONCHAIN_NECESSITY " : onchain . onchain_necessity_score ,
" VALUE_ACCRUAL_QUALITY " : value . value_accrual_quality_score ,
" NETWORK_EFFECT_POTENTIAL " : min ( 100 , 50 + ( 20 if " provider " in text else 0 ) + ( 15 if " reputation " in text else 0 ) ) ,
" TOKENOMICS_SUSTAINABILITY " : value . tokenomics_sustainability_score ,
" BOOTSTRAPPABILITY " : 78 if " testnet " in text or " fake credits " in text else 55 ,
" AUTONOMOUS_OPERABILITY " : autonomy . autonomous_operability_score ,
" SECURITY_MODEL_QUALITY " : min ( 100 , 45 + sum ( 8 for term in [ " contract " , " oracle " , " key " , " pause " , " treasury " , " slashing " ] if term in text ) ) ,
" REGULATORY_MANAGEABILITY " : policy . regulatory_manageability_score ,
2026-08-16 19:31:15 +07:00
" PRE_TOKEN_MONETIZATION_POTENTIAL " : pretoken . pre_token_monetization_potential ,
2026-08-16 18:12:50 +07:00
}
score = round ( sum ( component_scores . values ( ) ) / len ( component_scores ) - len ( red . flags ) * 4 , 1 )
decision = self . _crypto_decision ( component_scores , token . classification , red . flags )
2026-08-16 19:31:15 +07:00
autonomy_class = CryptoAutonomyClass . AUTONOMOUS_CRYPTO if autonomy . autonomous_operability_score > = 70 else CryptoAutonomyClass . ASSISTED_CRYPTO
2026-08-16 22:46:24 +07:00
counterfactual = token . metadata . get ( " sol_token_utility_judge " , { } ) if isinstance ( token . metadata , dict ) else { }
return { " proposal_id " : str ( proposal . id ) , " company " : proposal . title , " one_line_thesis " : proposal . pitch . get ( " One-line thesis " , " " ) , " product_thesis " : proposal . protocol_thesis . product_thesis , " protocol_thesis " : proposal . protocol_thesis . protocol_thesis , " user " : proposal . target_customer , " pre_token_business " : pretoken . pre_token_business , " pre_token_monetization " : pretoken . mode , " pre_token_monetization_potential " : pretoken . pre_token_monetization_potential , " pre_token_revenue_ladder " : pretoken . revenue_ladder , " protocol_economy " : proposal . protocol_thesis . protocol_thesis , " token_economy " : proposal . protocol_thesis . token_thesis , " token_thesis " : proposal . protocol_thesis . token_thesis , " why_onchain " : proposal . onchain_assessment . rationale , " why_token " : token . rationale , " token_role_decomposition " : roles . roles , " token_utility_scores " : utility_profile , " strong_token_roles " : token . metadata . get ( " strong_token_roles " , [ ] ) , " strong_structural_roles " : token . metadata . get ( " strong_structural_roles " , [ ] ) , " argument_for_native_token " : token . metadata . get ( " argument_for_native_token " , " " ) , " argument_against_native_token " : token . metadata . get ( " argument_against_native_token " , " " ) , " stablecoin_counterfactual " : roles . stablecoin_counterfactual , " external_collateral_counterfactual " : token . metadata . get ( " external_collateral_counterfactual " , counterfactual . get ( " model_c_external_collateral " , { } ) ) , " native_token_removed_breaks " : token . metadata . get ( " native_token_removed_breaks " , [ ] ) , " native_token_removed_degradation " : token . metadata . get ( " native_token_removed_degradation " , " " ) , " native_token_removed_explanation " : token . metadata . get ( " native_token_removed_explanation " , " " ) , " native_token_removed_outcome " : roles . native_token_removed_outcome , " native_token_removed_degrades_protocol " : sim . summary . get ( " native_token_removed_degrades_protocol " , False ) , " token_utility " : token . utility_categories , " token_necessity_classification " : token . classification , " token_demand_loop " : proposal . token_demand_loop . loop , " value_capture " : proposal . value_capture . value_accrual , " network_effect " : proposal . protocol_thesis . network_effect , " bootstrap_plan " : proposal . protocol_thesis . bootstrap_plan , " autonomous_operability " : autonomy . autonomous_operability_score , " crypto_autonomy_class " : autonomy_class , " regulatory_manageability " : policy . regulatory_manageability_score , " security_assessment " : security . decision if security else " NOT_ASSESSED " , " security_risk " : component_scores [ " SECURITY_MODEL_QUALITY " ] , " guard_verdict " : security . decision if security else " NOT_ASSESSED " , " validation_experiment " : proposal . validation_plan , " component_scores " : component_scores , " value_accrual_quality " : value . value_accrual_quality_score , " tokenomics_sustainability " : value . tokenomics_sustainability_score , " simulation_summary " : sim . summary , " token_red_team_flags " : red . flags , " crypto_ic_decision " : decision , " crypto_ic_score " : score , " research " : proposal . metadata . get ( " research " , { } ) , " research_confidence " : proposal . metadata . get ( " research " , { } ) . get ( " research_status " , " RESEARCH_INSUFFICIENT " ) , " legal_review_required " : policy . legal_review_required }
2026-08-16 18:12:50 +07:00
def assess_autonomy ( self , proposal : CompanyProposal ) - > AutonomousOperabilityAssessment :
assessment = self . venture . assess_autonomous_operability ( proposal )
text = self . _proposal_text ( proposal )
penalty = 25 if any ( term in text for term in [ " exchange listing " , " market making " , " institutional integration " , " founder evangelism " ] ) else 0
score = max ( 0 , assessment . autonomous_operability_score - penalty )
minutes = assessment . minutes_per_week_human + ( 30 if penalty else 0 )
gate = AutonomousGateResult . AUTONOMOUS_ELIGIBLE if score > = 75 and minutes < = 30 else AutonomousGateResult . AUTONOMOUS_BORDERLINE if score > = 60 else AutonomousGateResult . ASSISTED_ONLY
assessment . venture_track = VentureTrack . CRYPTO_PROTOCOL
assessment . gate_result = gate
assessment . autonomous_operability_score = score
assessment . minutes_per_week_human = minutes
assessment . human_actions_required = list ( dict . fromkeys ( [ * assessment . human_actions_required , " legal review " , " security review " , " mainnet/issuance approval gate " ] ) )
assessment . human_action_categories = list ( dict . fromkeys ( [ * assessment . human_action_categories , " LEGAL_GATE " , " SECURITY_GATE " ] ) )
assessment . platform_blockers = list ( dict . fromkeys ( [ * assessment . platform_blockers , " LEGAL_REVIEW_REQUIRED " , " SMART_CONTRACT_AUDIT " , " KEY_MANAGEMENT " , " TESTNET_DEPLOYMENT " ] ) )
assessment . validation_offer = { * * assessment . validation_offer , " type " : " testnet/local simulation " , " token_required " : False }
assessment . end_state_business_model = { * * assessment . end_state_business_model , " type " : " usage-fee protocol " , " token_sale " : False , " mainnet_requires_human_gate " : True }
assessment . rationale = assessment . rationale + " Crypto overlay: V0.1 can build/testnet/simulate autonomously, but issuance, fundraising, and mainnet deployment stop at legal/security gates. "
assessment . save ( update_fields = [ " venture_track " , " gate_result " , " autonomous_operability_score " , " minutes_per_week_human " , " human_actions_required " , " human_action_categories " , " platform_blockers " , " validation_offer " , " end_state_business_model " , " rationale " , " updated_at " ] )
return assessment
def _crypto_decision ( self , scores : dict [ str , float ] , classification : str , flags : list [ str ] ) - > str :
if classification == TokenNecessityClassification . TOKEN_UNNECESSARY :
return CryptoICDecisionType . REJECT_TOKEN_NOT_NEEDED
if classification == TokenNecessityClassification . TOKEN_OPTIONAL :
2026-08-16 21:56:09 +07:00
return CryptoICDecisionType . REJECT_TOKEN_UTILITY_WEAK
2026-08-16 18:12:50 +07:00
if TokenRedTeamFlag . SPECULATION_DEPENDENT in flags :
return CryptoICDecisionType . REJECT_SPECULATIVE
if scores [ " REGULATORY_MANAGEABILITY " ] < 55 :
return CryptoICDecisionType . REJECT_REGULATORY_RISK
if scores [ " TOKENOMICS_SUSTAINABILITY " ] < 65 or scores [ " VALUE_ACCRUAL_QUALITY " ] < 65 :
return CryptoICDecisionType . REVISE_TOKEN_MODEL
2026-08-16 21:56:09 +07:00
if scores [ " TOKEN_NECESSITY " ] > = 85 and scores [ " ONCHAIN_NECESSITY " ] > = 80 and scores [ " REAL_USAGE_DEMAND " ] > = 75 and 55 < = scores [ " AUTONOMOUS_OPERABILITY " ] < 70 :
return CryptoICDecisionType . ASSISTED_CRYPTO_HIGH_POTENTIAL
2026-08-16 18:12:50 +07:00
if scores [ " TOKEN_NECESSITY " ] > = 82 and scores [ " ONCHAIN_NECESSITY " ] > = 75 :
return CryptoICDecisionType . TESTNET_PILOT
return CryptoICDecisionType . PROTOCOL_VALIDATE
def _sol_final_ic_adjustment ( self , row : dict [ str , Any ] ) - > dict [ str , Any ] :
2026-08-16 23:32:55 +07:00
compact_row = { key : row . get ( key ) for key in [ " company " , " product_thesis " , " protocol_thesis " , " token_thesis " , " why_token " , " token_necessity_classification " , " token_utility_scores " , " strong_token_roles " , " strong_structural_roles " , " argument_for_native_token " , " argument_against_native_token " , " external_collateral_counterfactual " , " native_token_removed_degradation " , " native_token_removed_explanation " , " token_red_team_flags " , " component_scores " , " crypto_ic_score " , " crypto_ic_decision " ] }
review = self . _sol_json ( " Final Crypto IC review V0.3.2B. Return JSON only with score_adjustment -20..20, decision from TESTNET_PILOT, PROTOCOL_VALIDATE, REVISE_TOKEN_MODEL, ASSISTED_CRYPTO_HIGH_POTENTIAL, WATCHLIST, ROUTE_TO_VENTURE_STUDIO, REJECT_TOKEN_NOT_NEEDED, REJECT_TOKEN_UTILITY_WEAK, REJECT_ONCHAIN_NOT_NEEDED, REJECT_SECURITY_MODEL, REJECT_ECONOMIC_MODEL, REJECT_AUTONOMY, REJECT_NO_DEMAND, and rationale. Consider the repaired token utility judge evidence, red-team flags, and component scores. Do not promote weak token ideas or fill finalist slots. Row: " + json . dumps ( compact_row , default = str ) )
2026-08-16 18:12:50 +07:00
if not review :
return row
adjustment = max ( - 20 , min ( 20 , float ( review . get ( " score_adjustment " , 0 ) ) ) )
decision = str ( review . get ( " decision " , row [ " crypto_ic_decision " ] ) )
if decision not in CryptoICDecisionType . values :
decision = row [ " crypto_ic_decision " ]
return { * * row , " crypto_ic_score " : round ( max ( 0 , min ( 100 , row [ " crypto_ic_score " ] + adjustment ) ) , 1 ) , " crypto_ic_decision " : decision , " sol_final_ic_review " : review }
def _qualifies_finalist ( self , row : dict [ str , Any ] ) - > bool :
scores = row [ " component_scores " ]
2026-08-16 21:56:09 +07:00
structural_roles = set ( row . get ( " strong_structural_roles " , [ ] ) )
return row [ " token_necessity_classification " ] in { TokenNecessityClassification . TOKEN_ESSENTIAL , TokenNecessityClassification . TOKEN_STRONGLY_JUSTIFIED } and len ( row . get ( " strong_token_roles " , [ ] ) ) > = 2 and structural_roles & STRUCTURAL_TOKEN_ROLES and scores [ " TOKEN_NECESSITY " ] > = 75 and scores [ " REAL_USAGE_DEMAND " ] > = 65 and scores [ " ONCHAIN_NECESSITY " ] > = 70 and scores [ " VALUE_ACCRUAL_QUALITY " ] > = 65 and scores [ " TOKENOMICS_SUSTAINABILITY " ] > = 65 and scores [ " AUTONOMOUS_OPERABILITY " ] > = 70 and row . get ( " security_assessment " ) != ProtocolSecurityDecision . BLOCK_TESTNET and row . get ( " native_token_removed_degrades_protocol " ) is True
2026-08-16 18:12:50 +07:00
def _crypto_concentration ( self , rows : list [ dict [ str , Any ] ] ) - > dict [ str , Any ] :
categories = Counter ( row [ " company " ] . split ( ) [ 0 ] for row in rows )
utilities = Counter ( util for row in rows for util in row . get ( " token_utility " , [ ] ) )
return { " protocol_category_distribution " : dict ( categories ) , " token_utility_distribution " : dict ( utilities ) , " saturation_flags " : [ name for name , count in categories . items ( ) if count > = 3 ] }
def _infer_utilities ( self , text : str ) - > list [ str ] :
lowered = text . lower ( )
utilities = [ ]
if " fee " in lowered or " settlement " in lowered :
utilities . append ( " protocol fee settlement " )
if " stake " in lowered :
utilities . append ( " staking tied to measurable service quality " )
if " slash " in lowered :
utilities . append ( " slashing / economic guarantees " )
if " market " in lowered or " provider " in lowered :
utilities . append ( " decentralized marketplace coordination " )
if " attestation " in lowered or " proof " in lowered :
utilities . append ( " proof/attestation markets " )
return utilities or [ " token utility not proven " ]
def _proposal_text ( self , proposal : CompanyProposal ) - > str :
crypto = proposal . metadata . get ( " crypto " , { } ) if isinstance ( proposal . metadata , dict ) else { }
return " " . join ( [ proposal . title , proposal . description , proposal . problem , proposal . target_customer , proposal . proposed_solution , proposal . business_model , proposal . validation_plan , json . dumps ( crypto , default = str ) ] ) . lower ( )
2026-08-16 22:46:24 +07:00
def _design_text ( self , proposal : CompanyProposal ) - > str :
parts = [ proposal . title , proposal . description , proposal . problem , proposal . target_customer , proposal . proposed_solution , proposal . business_model , proposal . pricing_hypothesis , proposal . acquisition_strategy , proposal . validation_plan ]
if hasattr ( proposal , " protocol_thesis " ) :
parts . extend ( [ proposal . protocol_thesis . product_thesis , proposal . protocol_thesis . protocol_thesis , proposal . protocol_thesis . token_thesis , proposal . protocol_thesis . network_effect , proposal . protocol_thesis . bootstrap_plan , json . dumps ( proposal . protocol_thesis . utility_categories , default = str ) ] )
if hasattr ( proposal , " token_demand_loop " ) :
parts . append ( json . dumps ( proposal . token_demand_loop . loop , default = str ) )
crypto = proposal . metadata . get ( " crypto " , { } ) if isinstance ( proposal . metadata , dict ) else { }
actual = { key : crypto . get ( key ) for key in [ " product_thesis " , " protocol_thesis " , " token_thesis " , " token_utility " , " token_demand_loop " , " value_capture " , " network_effect " , " bootstrap_plan " , " security_model " , " token_roles " , " mechanism_fingerprint " ] if key in crypto }
parts . append ( json . dumps ( actual , default = str ) )
return " " . join ( str ( part ) for part in parts if part ) . lower ( )
2026-08-16 18:12:50 +07:00
def _positive_phrase_present ( self , text : str , phrase : str ) - > bool :
phrase = phrase . lower ( )
for match in re . finditer ( re . escape ( phrase ) , text ) :
prefix = text [ max ( 0 , match . start ( ) - 40 ) : match . start ( ) ]
if any ( negation in prefix for negation in [ " no " , " not " , " without " , " disabled " , " disable " , " prohibit " , " forbid " , " never " ] ) :
continue
return True
return False
2026-08-16 22:59:30 +07:00
def _complete_token_utility_judge ( self , prompt : str , roles : dict [ str , Any ] , * , attempts : int = 3 ) - > dict [ str , Any ] :
if self . router is None or self . final_ic_model_hint not in self . router . providers :
return { }
retry_hint = " "
last_missing : list [ str ] = [ ]
for attempt in range ( attempts ) :
review = self . _sol_json ( prompt + retry_hint )
2026-08-16 23:32:55 +07:00
review = self . _normalize_token_judge_response ( review )
2026-08-16 22:59:30 +07:00
missing = self . _token_judge_missing_fields ( review , roles )
if not missing :
return review
last_missing = missing
retry_hint = " \n Previous token utility judge response was rejected because these required fields or rationale checks were empty/incomplete: " + json . dumps ( missing ) + " . Return a complete JSON object only. "
raise ValueError ( " Incomplete Sol token utility judge response: " + " , " . join ( last_missing ) )
2026-08-16 23:32:55 +07:00
def _normalize_token_judge_response ( self , review : dict [ str , Any ] ) - > dict [ str , Any ] :
if not isinstance ( review , dict ) :
return { }
normalized = dict ( review )
counterfactual = normalized . get ( " counterfactual_analysis " )
if isinstance ( counterfactual , dict ) and self . _empty_judge_value ( normalized . get ( " external_collateral_counterfactual " ) ) :
nested = counterfactual . get ( " external_collateral_counterfactual " )
if not self . _empty_judge_value ( nested ) :
normalized [ " external_collateral_counterfactual " ] = nested
scores = normalized . get ( " utility_scores " )
if isinstance ( scores , dict ) :
normalized [ " utility_scores " ] = { str ( key ) . upper ( ) : value for key , value in scores . items ( ) }
return normalized
2026-08-16 22:59:30 +07:00
def _token_judge_missing_fields ( self , review : dict [ str , Any ] , roles : dict [ str , Any ] ) - > list [ str ] :
if not review :
return [ " judge_response " ]
missing = [ field for field in TOKEN_JUDGE_REQUIRED_FIELDS if self . _empty_judge_value ( review . get ( field ) ) ]
classification = str ( review . get ( " token_classification " ) or review . get ( " classification " ) or " " )
if classification not in TokenNecessityClassification . values :
missing . append ( " token_classification " )
degradation = str ( review . get ( " native_token_removed_degradation " ) or " " ) . upper ( )
if degradation not in { " NONE " , " MINOR " , " MODERATE " , " MATERIAL " , " CRITICAL " } :
missing . append ( " native_token_removed_degradation " )
rationale = str ( review . get ( " final_rationale " ) or " " ) . lower ( )
counterfactual = review . get ( " counterfactual_analysis " , { } )
if not isinstance ( counterfactual , dict ) :
counterfactual = { }
external_identical = bool ( counterfactual . get ( " external_collateral_identical_security " ) )
stable_identical = bool ( counterfactual . get ( " stable_collateral_identical_security " ) )
structural_count = sum ( 1 for role , value in roles . items ( ) if role in STRUCTURAL_TOKEN_ROLES and str ( value ) . upper ( ) in { " REQUIRED " , " STRONGLY_USEFUL " } )
contradiction = not external_identical and not stable_identical and degradation == " MATERIAL " and structural_count > = 2
if classification == TokenNecessityClassification . TOKEN_OPTIONAL :
has_preference_answer = any ( asset in rationale for asset in [ " eth " , " usdc " , " external collateral " , " stablecoin " ] ) and any ( term in rationale for term in [ " prefer " , " simpler " , " liquid " , " lower " , " regulatory " , " volatility " , " issuance " , " cost " , " risk " ] )
if not has_preference_answer :
missing . append ( " final_rationale_optional_collateral_preference " )
if contradiction and not any ( term in rationale for term in [ " despite " , " even though " , " still fail " , " not justify " , " outweigh " ] ) :
missing . append ( " final_rationale_material_degradation_contradiction " )
if classification in { TokenNecessityClassification . TOKEN_ESSENTIAL , TokenNecessityClassification . TOKEN_STRONGLY_JUSTIFIED } :
has_specific_property = any ( asset in rationale for asset in [ " eth " , " usdc " , " external collateral " , " stablecoin " ] ) and any ( term in rationale for term in [ " cannot " , " not reproduce " , " cannot reproduce " , " insufficient " , " protocol-specific " , " not economically " ] )
if not has_specific_property :
missing . append ( " final_rationale_protocol_specific_non_reproducible_property " )
return missing
def _empty_judge_value ( self , value : Any ) - > bool :
if value is None :
return True
if isinstance ( value , str ) :
return not value . strip ( )
if isinstance ( value , ( list , tuple , set , dict ) ) :
return len ( value ) == 0
return False
2026-08-16 18:12:50 +07:00
def _sol_json ( self , prompt : str ) - > dict [ str , Any ] :
if self . router is None or self . final_ic_model_hint not in self . router . providers :
return { }
2026-08-16 21:00:15 +07:00
return self . _model_json ( self . final_ic_model_hint , prompt , purpose = ModelCapability . REASONING )
def _model_json ( self , model_hint : str , prompt : str , * , purpose : str ) - > dict [ str , Any ] :
if self . router is None or model_hint not in self . router . providers :
return { }
2026-08-16 18:12:50 +07:00
try :
2026-08-16 21:00:15 +07:00
response = self . router . complete ( ModelRequestContract ( purpose = purpose , model_hint = model_hint , prompt = prompt ) )
2026-08-16 18:12:50 +07:00
parsed = extract_json_object ( response . content )
return parsed if isinstance ( parsed , dict ) else { }
except Exception :
return { }
def _as_list ( self , value : Any ) - > list [ Any ] :
if isinstance ( value , list ) :
return value
if value in ( None , " " ) :
return [ ]
return [ value ]
2026-08-16 18:18:15 +07:00
def _confidence ( self , value : Any ) - > float :
labels = { " low " : 0.35 , " medium " : 0.55 , " moderate " : 0.6 , " high " : 0.75 , " very high " : 0.85 }
if isinstance ( value , str ) :
lowered = value . strip ( ) . lower ( )
if lowered in labels :
return labels [ lowered ]
try :
return max ( 0.0 , min ( 1.0 , float ( value ) ) )
except ( TypeError , ValueError ) :
return 0.55
2026-08-16 18:12:50 +07:00
def _fingerprint ( self , value : str ) - > str :
tokens = sorted ( set ( re . findall ( r " [a-z0-9] { 4,} " , value . lower ( ) ) ) )
return hashlib . sha256 ( " | " . join ( tokens ) . encode ( " utf-8 " ) ) . hexdigest ( ) [ : 32 ]
def _artifact ( self , proposal , mandate , artifact_type : str , name : str , content : dict [ str , Any ] , readable : str , generated_by : str , * , graph_run = None ) - > VentureArtifact :
return VentureArtifact . objects . create ( proposal = proposal , mandate = mandate , graph_run = graph_run , artifact_type = artifact_type , name = name , content = content , readable = readable , generated_by = generated_by )
def _readable_report ( self , content : dict [ str , Any ] ) - > str :
2026-08-16 21:56:09 +07:00
lines = [ " # CRYPTO VENTURE COHORT V0.3.1 " , " " , f " Cohort ID: { content [ ' cohort_id ' ] } " , f " Crypto survivors: { content [ ' crypto_survivors ' ] } " , " " , " ## Ranking " ]
2026-08-16 18:12:50 +07:00
for row in content [ " ranking " ] :
lines . append ( f " - Rank { row . get ( ' rank ' ) } : { row [ ' company ' ] } | { row [ ' crypto_ic_decision ' ] } | score { row [ ' crypto_ic_score ' ] } | token { row [ ' token_necessity_classification ' ] } " )
lines . append ( " " )
lines . append ( " ## Top 3 " )
if content [ " top_3 " ] :
lines . extend ( f " - { row [ ' company ' ] } " for row in content [ " top_3 " ] )
else :
lines . append ( " Fewer than 3 qualified; weak token ideas were not promoted. " )
lines . append ( " " )
2026-08-16 19:31:15 +07:00
lines . append ( " Stop condition: no token/NFT sale, fundraising, mainnet issuance, user contact, or real spend. " )
2026-08-16 18:12:50 +07:00
return " \n " . join ( lines )