TechLens Signal Guide
Auto-generated from signal definitions. Run python scripts/generate_signal_docs.py to regenerate.
Pipeline Overview
The FULL_ANALYSIS pipeline runs 20 stages in order.
Dashed borders indicate SLM-dependent stages that are skipped when no local model is available.
graph TB
subgraph "File Discovery"
direction LR
S0["filter_files
Walk repo, select source files"]
S1["create_manager
Instantiate per-file score accumulator"]
end
subgraph "Signal Collection"
direction LR
S2["ast_analysis
code-analysis structural pipeline (optional)"]
S3["git_density
Git density, author count, co-change"]
S4["contributor_attribution
Contributor attribution enrichment"]
S5["token_metrics
Cyclomatic complexity, operands, operators, fanout"]
S6["cognitive_metric
AST cognitive complexity (max + total per file)"]
S7["code_metrics
Control flow, definitions, comments, glue, domain tokens"]
S8["test_coverage
Map test files to source files"]
S9["derived_metrics
Halstead, maintainability index, TIOBE"]
S10["cognitive_maintainability
Maintainability index with cognitive complexity in place of Halstead"]
S11["moat_signals
API surface, data accumulation, realtime, governance, regulatory"]
S12["ast_signals
Dead code, dependency cycles, layer violations"]
S13["churn_metric
Per-file near-rewrite churn score"]
S14["change_density
Change density (git density x missing protective factors)"]
S15["ai_adoption
AI tool adoption detection"]
end
subgraph "Scoring"
direction LR
S16["composite_scores
Weighted composite scoring + top-files ranking"]
end
subgraph "SLM (optional)"
direction LR
S17["lm_code_value
SLM: uniqueness, difficulty, quality"]
S18["file_descriptions
SLM: per-file descriptions + program synthesis"]
S19["slm_post_filter
SLM: outlier queries (code value + glue assessment)"]
end
S0 --> S1
S1 --> S2
S2 --> S3
S3 --> S4
S4 --> S5
S5 --> S6
S6 --> S7
S7 --> S8
S8 --> S9
S9 --> S10
S10 --> S11
S11 --> S12
S12 --> S13
S13 --> S14
S14 --> S15
S15 --> S16
S16 --> S17
S17 --> S18
S18 --> S19
style S17 stroke-dasharray: 5 5
style S18 stroke-dasharray: 5 5
style S19 stroke-dasharray: 5 5
Signal → Composite Score
Signals feed into composite scores with weighted contributions. Dashed arrows indicate inverted signals (lower raw value = higher contribution). ⚛ marks signals requiring a local SLM.
architecturegitheuristicslmstatic_analysis
graph LR
subgraph " "
direction LR
control_flow_density["control_flow_density"]:::heuristic
definition_density["definition_density"]:::heuristic
comment_ratio["comment_ratio"]:::heuristic
test_coverage_boosted["test_coverage_boosted"]:::architecture
duplication_ratio["duplication_ratio"]:::heuristic
end
engineering_score(["engineering_score"]):::composite
subgraph " "
direction LR
lm_uniqueness["lm_uniqueness ⚛"]:::slm
lm_complexity["lm_complexity ⚛"]:::slm
lm_quality["lm_quality ⚛"]:::slm
end
lm_code_value_score(["lm_code_value_score"]):::composite
subgraph " "
direction LR
domain_match_density["domain_match_density"]:::heuristic
gluemarker_ratio["gluemarker_ratio"]:::heuristic
external_call_ratio["external_call_ratio"]:::heuristic
api_surface_ratio["api_surface_ratio"]:::architecture
realtime_pattern_density["realtime_pattern_density"]:::architecture
data_accumulation_pattern["data_accumulation_pattern"]:::architecture
governance_workflow_density["governance_workflow_density"]:::architecture
regulatory_token_density["regulatory_token_density"]:::architecture
end
moat_score(["moat_score"]):::composite
control_flow_density -->|15%| engineering_score
definition_density -->|15%| engineering_score
comment_ratio -->|15%| engineering_score
test_coverage_boosted -->|30%| engineering_score
duplication_ratio -.->|25% inv| engineering_score
lm_uniqueness -->|33%| lm_code_value_score
lm_complexity -->|33%| lm_code_value_score
lm_quality -->|33%| lm_code_value_score
domain_match_density -->|20%| moat_score
gluemarker_ratio -.->|15% inv| moat_score
external_call_ratio -.->|12% inv| moat_score
api_surface_ratio -->|6%| moat_score
realtime_pattern_density -->|6%| moat_score
data_accumulation_pattern -->|10%| moat_score
governance_workflow_density -->|6%| moat_score
regulatory_token_density -->|12%| moat_score
classDef git fill:#4A90D9,color:#fff,stroke:#333
classDef heuristic fill:#50C878,color:#fff,stroke:#333
classDef architecture fill:#FF8C42,color:#fff,stroke:#333
classDef static_analysis fill:#9B59B6,color:#fff,stroke:#333
classDef slm fill:#E74C3C,color:#fff,stroke:#333
classDef composite fill:#2C3E50,color:#fff,stroke:#fff,font-size:16px
Composite Weight Distribution
pie title engineering_score "control_flow_density" : 15 "definition_density" : 15 "comment_ratio" : 15 "test_coverage_boosted" : 30 "duplication_ratio (inv)" : 25
pie title lm_code_value_score "lm_uniqueness" : 33 "lm_complexity" : 33 "lm_quality" : 33
pie title moat_score "domain_match_density" : 20 "gluemarker_ratio (inv)" : 15 "external_call_ratio (inv)" : 12 "api_surface_ratio" : 6 "realtime_pattern_density" : 6 "data_accumulation_pattern" : 10 "governance_workflow_density" : 6 "regulatory_token_density" : 12
Signal Glossary
Click a signal to see what it measures. Per-file signals produce one value per source file; repo-level signals produce a single value for the entire repository.
Per-file (31)
git_densitygitgitNormalized change activity score from git history
Answers the four most common workshop questions at once: Where is active development focused? Who are the critical developers? What happens if they leave? Which components are secretly coupled? These findings directly influence retention clauses, earnout structures, and integration timelines.author_countgitgitNormalized count of distinct commit authors per file
Answers the four most common workshop questions at once: Where is active development focused? Who are the critical developers? What happens if they leave? Which components are secretly coupled? These findings directly influence retention clauses, earnout structures, and integration timelines.cochangegitgitNormalized co-change coupling frequency per file
Answers the four most common workshop questions at once: Where is active development focused? Who are the critical developers? What happens if they leave? Which components are secretly coupled? These findings directly influence retention clauses, earnout structures, and integration timelines.comment_density_hotheuristicPer-file interaction signal: comment ratio * git density
Documentation culture is a leading indicator of post-close maintenance risk. Near-zero comments + high change frequency = institutional knowledge trapped in developers' heads. Directly affects knowledge transfer timelines and key-person retention priorities.test_coveragearchitecturePer-file test coverage weight: binary 1.0/0.0 from naming heuristics, replaced by continuous AST coverage ratio (0.0-1.0) when ast_test_coverage_ratio is available
Reveals engineering discipline. Low test coverage tells an investor the team ships without a safety net. The absence of tests is one of the most common findings that changes rebuild estimates and post-close stabilization budgets.test_coverage_boostedarchitectureChurn-weighted boost for tested files (test_coverage * git_density)
Reveals engineering discipline. Low test coverage tells an investor the team ships without a safety net. The absence of tests is one of the most common findings that changes rebuild estimates and post-close stabilization budgets.slm_value_scoreSLMslmSLM-assessed value score per individual source file
Enables 'Is this code worth acquiring?' as a scored, benchmarkable answer. Per-file IP identification transforms workshops. Rebuild estimation with AI-assessed complexity.cyclomatic_complexitystatic_analysisMcCabe cyclomatic complexity per file
Measures the number of independent execution paths through the code. High cyclomatic complexity means more test cases needed for full coverage and higher probability of latent defects — directly impacting post-close stabilization effort.operands_sumstatic_analysisTotal operand token count per file
Raw input for Halstead metrics. Total operand count reflects data volume flowing through the code — higher counts indicate files doing substantive data transformation rather than simple pass-through.operands_uniquestatic_analysisUnique operand token count per file
Vocabulary breadth of data elements. A file with many unique operands is manipulating a rich data model, suggesting domain-specific logic that is harder to replicate or replace with generic tooling.operators_sumstatic_analysisTotal operator token count per file
Raw input for Halstead metrics. High operator counts relative to operands indicate dense control logic and data manipulation, contributing to implementation effort estimates.operators_uniquestatic_analysisUnique operator token count per file
Indicates the breadth of language features and constructs used. Files leveraging more unique operators tend to implement more sophisticated algorithms that require deeper expertise to maintain.definitions_countstatic_analysisUnique function and class definition count per file
Counts distinct function and class definitions via Pygments tokens. High definition counts indicate files that declare substantial API surface — more definitions mean more contracts to maintain, test, and document.halstead_volumestatic_analysisHalstead program volume
Measures the information content of the code in bits. High volume files contain more logic to understand, test, and maintain — directly proportional to the knowledge transfer effort required post-acquisition.halstead_difficultystatic_analysisHalstead program difficulty
Quantifies how hard the code is to write or understand. High difficulty files are error-prone to modify and require senior engineers — a factor in retention planning and post-close staffing decisions.halstead_effortstatic_analysisHalstead implementation effort
Enables rebuild estimation and t-shirt sizing. The top 10 files account for 60% of total comprehension effort, giving concrete input for post-close staffing and timeline planning.halstead_bugpropstatic_analysisHalstead estimated bug propensity
Predicts the expected number of delivered defects based on code volume. Files with high bug propensity are where post-close quality issues will concentrate — informing QA resource allocation and stabilization timelines.halstead_timerequiredstatic_analysisHalstead estimated implementation time
Estimates implementation time in seconds per file. High values flag modules that will take longest to rewrite or onboard — giving concrete input for rebuild timelines and staffing plans.maintainability_indexstatic_analysisMicrosoft's Maintainability Index variant (0-100): a composite of Halstead Volume, Cyclomatic Complexity, and Lines of Code. Originally defined by Oman/Hagemeister (Univ. Idaho/SEI, 1992); the Microsoft formulation popularized by Visual Studio is what most modern tooling — including ours — implements.
Ready-made quality score on a 0-100 scale that's immediately interpretable. 'This repo scores 35 on maintainability, bottom quartile across 200+ codebases we've assessed' is a finding that lands in investment committee presentations.cognitive_complexitystatic_analysisSonar-style cognitive complexity of the most complex entity in the file (max across functions/methods)
Estimates the comprehension cost of the hardest function to read in the file. Unlike cyclomatic complexity (which counts independent paths), cognitive complexity penalises nesting and ignores shorthand control flow — a much closer proxy for the cognitive load a reviewer or new hire actually pays. High max scores flag the entities that will dominate post-close onboarding and code-review time.cognitive_complexity_totalstatic_analysisSum of Sonar-style cognitive complexity across all entities in the file
Aggregates the whole-file comprehension burden, not just the worst entity. A file with 20 moderately complex functions can be harder to carry than one with a single hairy function — this signal surfaces those distributed-complexity files that single-entity maxima miss, and feeds the cognitive maintainability index.maintainability_index_cognitivestatic_analysisCognitive-flavored SEI maintainability index (0-100)
A 0-100 maintainability score built from comprehension cost rather than Halstead's algebraic volume. Where the classic index can flatter concise-but-dense files (low volume, high difficulty to read), the cognitive variant penalises nested control flow and cumulative entity complexity the way reviewers actually feel it. Pairs with the classic MI so investment-committee narratives can distinguish 'small but tangled' from 'genuinely simple'.fanout_internalstatic_analysisCount of unique internal (relative) imports per file
Measures internal coupling. Files that import many other project files are integration points — complex to modify and test because changes ripple across the dependency chain.fanout_externalstatic_analysisCount of unique external imports per file
Measures external dependency at the file level. Files pulling in many third-party libraries are vulnerable to vendor changes and are often glue code rather than proprietary logic.tiobestatic_analysisTIOBE quality index (0-100)
Industry-standard composite quality score combining complexity, code size, and duplication. Enables cross-repo benchmarking: 'This file scores 45/100, below the threshold for maintainable production code.'pylintstatic_analysisPylint-style quality score (0-100)
Widely recognized quality score in the Python ecosystem. Provides a familiar benchmark that engineering teams and technical advisors already understand, reducing friction in due-diligence conversations.file_rolestatic_analysisSemantic role classification per file (generated, vendor, lock, build_artifact, fixture, test, migration, view, controller, model, service, repository, middleware, config, infra, util, unspecified)
Enables targeted analysis by distinguishing code that matters (business logic, controllers, models) from code that doesn't (generated, vendored, config). Downstream signals can weight files differently based on their role.churn_scoregitgitPer-file near-rewrite churn score: sum of log10(loc) * min(change_frac, 1.0) across qualifying near-rewrite events (loc≥200, change_frac≥0.8, deletions>0). Code files only — tests and non-code extensions are excluded.
Surfaces files that have been rewritten near-completely two or more times — the kind of pathology that signals an unsettled design or AI-thrashing rather than healthy iteration. Targets code files only (test churn is expected; this metric ignores it).is_churninggitgitBoolean derived from churn_score: True iff the file has at least EVENT_COUNT_MIN=2 qualifying near-rewrite events in its git history.
Clean binary view of the churn signal — used for the repo-level ``churn_files`` list that drives at-a-glance hotspot reporting.change_densitygitgitPer-file score: git_density * (1 - protective_factors). Protective factors: has_tests (0.4), multiple authors (0.3), low complexity (0.3). High density with good tests and multiple authors scores low. High density with no tests, single author, and high complexity scores high. Distinct from `churn_score` — that one counts near-rewrite events on code files; this measures activity-rate risk.
Activity alone is ambiguous — active development is healthy. Change density isolates files where high change velocity lacks protective factors (tests, shared ownership, manageable complexity), surfacing true maintenance debt and key-person risk.import_indegreearchitectureNormalized count of internal imports pointing to this file (from codeanalysis AST edges)
Identifies architectural bottlenecks and single points of failure. A file imported by dozens of others is both the most valuable and the most dangerous — any bug there cascades across the entire system, and it cannot be replaced without coordinated refactoring.
Repo-level (26)
bus_factor_filesgitgitCount of business-logic files (source, model, service, controller, repository, middleware, util, view) with only one author (bus-factor risk). Excludes vendor, generated, lock, build artifact, fixture, test, migration, config, and infra files.
Answers the four most common workshop questions at once: Where is active development focused? Who are the critical developers? What happens if they leave? Which components are secretly coupled? These findings directly influence retention clauses, earnout structures, and integration timelines.control_flow_densityheuristicControl-flow statements per 100 code lines. Denominator is AST-derived code lines (comments excluded) when AST metadata is available; in the regex fallback path it is non-blank lines (comments included) since the authoritative comment counter lives in stage_token_metrics, not code_metrics.
Identifies where business rules concentrate. High control flow density in a few files means proprietary decision logic is packed into complex code, driving up rebuild cost. Low density across the repo may indicate the product is mostly glue with little original logic.definition_densityheuristicDefinitions (functions, classes) per 100 code lines. Denominator follows the same AST-vs-regex-fallback split as control_flow_density — comments-excluded with AST metadata, comments-included in the regex fallback.
Indicates code modularity and reuse patterns. Low definition density suggests monolithic functions doing too much, increasing maintenance cost.comment_ratioheuristicRepo-wide fraction of comment characters (LOC-weighted average of per-file Pygments-tokenized comment-character ratios)
Documentation culture is a leading indicator of post-close maintenance risk. Near-zero comments + high change frequency = institutional knowledge trapped in developers' heads. Directly affects knowledge transfer timelines and key-person retention priorities.test_coverage_ratioarchitectureThe active test-coverage measurement: prefers AST-resolved entity reachability when available, falls back to file-pairing.
Reveals engineering discipline. Low test coverage tells an investor the team ships without a safety net. The absence of tests is one of the most common findings that changes rebuild estimates and post-close stabilization budgets.domain_token_densityheuristicRatio of domain-specific vocabulary to generic tokens
Unlocks the most strategically important signal. Function names like 'calculate_actuarial_reserve' or 'apply_regulatory_haircut' reveal the depth of proprietary domain knowledge that can't be replicated by hiring generic developers.domain_match_densityheuristicRatio of domain-specific vocabulary matches (stemmed + prefix)
Measures positive matches against curated domain dictionaries (fintech, healthtech, enterprise). Unlike generic density, this confirms the codebase actually uses specialized vocabulary — a strong indicator of proprietary domain logic.gluemarker_ratioheuristicWeighted ratio of glue/boilerplate markers to total lines
Quantifies how much of the codebase is commodity wiring vs. substantive logic. A product that's 70% glue code has a fundamentally different value proposition than one with deep proprietary processing. Directly answers: 'How much of this is replaceable by off-the-shelf tools or AI?'external_call_ratioheuristicRatio of external library calls to total function calls
Measures how self-contained the product's value is. High external dependency means vulnerability to vendor pricing changes, API deprecation, or third-party outages. Inverse relationship to defensibility.duplication_ratioheuristicRatio of duplicated code blocks across files
High duplication is a direct indicator of technical debt and rebuild cost. Copy-pasted code means bugs exist in multiple places, refactoring is more expensive than it appears, and the team's engineering practices are weak.lm_uniquenessSLMslmLM-assessed code uniqueness/novelty
Enables 'Is this code worth acquiring?' as a scored, benchmarkable answer. Per-file IP identification transforms workshops. Rebuild estimation with AI-assessed complexity.lm_complexitySLMslmLM-assessed implementation difficulty
Enables 'Is this code worth acquiring?' as a scored, benchmarkable answer. Per-file IP identification transforms workshops. Rebuild estimation with AI-assessed complexity.lm_qualitySLMslmLM-assessed code quality
Enables 'Is this code worth acquiring?' as a scored, benchmarkable answer. Per-file IP identification transforms workshops. Rebuild estimation with AI-assessed complexity.program_value_scoreSLMslmSLM-synthesized holistic program value from per-file summaries
Enables 'Is this code worth acquiring?' as a scored, benchmarkable answer. Per-file IP identification transforms workshops. Rebuild estimation with AI-assessed complexity.assessment_scoreSLMslmEngineered-vs-assembled verdict from chunk+merge SLM pipeline
Enables 'Is this code worth acquiring?' as a scored, benchmarkable answer. Per-file IP identification transforms workshops. Rebuild estimation with AI-assessed complexity.api_surface_ratioarchitectureRatio of API-exposed files (e.g. controllers, routes/routers, handlers, views, resolvers, resources, api/apis, endpoints). Measures what fraction of source files exposes external endpoints.
Detects interface control. A product with a large API surface that third parties integrate with creates switching costs proportional to the number of external consumers. More endpoints = more ecosystem dependence = stickier product.realtime_pattern_densityarchitectureRatio of realtime/event-driven dependencies to total dependencies
Detects a resilient AI moat. Low-latency and high-frequency domains (WebSocket, gRPC, streaming) are among the hardest for AI to replicate because they require real-time state management and performance engineering. Presence signals sticky technical complexity.data_accumulation_patterngitarchitectureMigration/seed files + git history span indicating data accumulation moat
Detects data flywheel effects. 200+ migration files represent years of schema evolution driven by real-world usage. The accumulated data model and the logic to manage it are often more valuable than the application code itself.governance_workflow_densityarchitectureDensity of governance/workflow paths and deps indicating process moat
Detects one of the stickiest moats: governance authority. Products with deep approval workflows, RBAC, and audit trails have switching costs that compound over time. Customers can't easily rip out a system that enforces their compliance processes.regulatory_token_densityarchitectureDensity of compliance/regulatory paths and deps indicating regulatory moat
Regulated industries create natural moats because compliance requirements raise the barrier to entry for competitors and AI. A codebase with deep HIPAA, PCI, or SOX implementations reflects years of regulatory domain knowledge that can't be shortcut.cochange_clustersgitgitClusters of files that frequently change together, detected via Louvain community detection
Reveals hidden architectural coupling. Files that always change together may be tightly coupled even if they have no import relationship. This informs modularization effort estimates and highlights integration risk during platform migrations.dead_code_ratiostatic_analysisRatio of unreachable or unused code to total lines (detects dead branches, unreferenced functions/classes)
Dead code inflates maintenance burden and obscures the real codebase size. A high ratio signals accumulated technical debt — developers must navigate and reason about code that serves no purpose, increasing onboarding time and defect risk.dependency_cycle_countstatic_analysisCount of circular dependency chains (imports that form loops at the module or package level)
Circular dependencies between files make the codebase resistant to modularisation and safe refactoring. Each cycle is a tightly coupled cluster that must be changed as a unit, increasing coordination cost and merge conflict risk.layer_violation_countstatic_analysisCount of imports that cross architectural layer boundaries (e.g., view calling repository directly in MVC). Only applies to MVC-shaped codebases.
Layer violations (e.g. a controller importing directly from the data layer, bypassing services) indicate architectural erosion. They increase the blast radius of changes and make it harder to replace or refactor individual layers independently.ai_adoptiongitai_adoptionAI tool adoption detection via config files and commit attribution. Covers evidence catalog E017-E028 (config files) and E009-E014 (git metadata).
Detects AI coding tool usage (Copilot, Claude Code, Cursor, Aider, Devin, Codex, etc.) via config files and git commit attribution patterns. Critical for software due-diligence assessment of AI adoption maturity.md_maintenancegitai_adoptionMaintenance signal for root-level CLAUDE.md / AGENTS.md: lifetime and 90-day change ratios plus per-author maintainer distribution. Flags 'exists but unmaintained' AI memory files.
CLAUDE.md / AGENTS.md sit in the AI's context window on every interaction. Stale memory files degrade output quality; this signal distinguishes 'has AI memory' from 'maintains AI memory'.
How compute_composite Works
- Collect contributions — iterate all
SignalDefinitions, find those with aCompositeContributionmatching the target composite name. - Skip missing — if a signal's value is
None(e.g. SLM unavailable, no git history), skip it entirely. Its weight is excluded from both numerator and denominator — the score degrades gracefully rather than penalizing. - Normalize — if
normalize_divisoris set, clamp:v = min(raw / divisor, 1.0). - Invert — if
inverted=True(lower-is-better signals like duplication), flip:v = 1.0 - v. - Accumulate —
weighted_sum += v * weight,total_weight += weight. - Re-normalize — final score =
weighted_sum / total_weight, so the result is always 0.0–1.0 regardless of which signals were available.