In type-challenges/type-challenges — a TypeScript challenge collection with 140 tracked functions, 3 of which score in the critical band — the highest structural risk is concentrated entirely in the scripts/ automation layer, not in the challenge definitions themselves. The top hotspot, generatePlayground in scripts/generate-play.ts, carries a risk score of 11.57 driven by its structural complexity (CC 18, fan-out 25) — but it hasn’t been touched in 271 days. These functions sit in the debt quadrant: they’ve accumulated structural weight across past development cycles and have been stable for nearly a year. That stability doesn’t eliminate the risk; it means the debt will surface as a high blast-radius problem whenever the automation layer is next changed.
The table below ranks functions by activity-weighted risk — a score that multiplies structural complexity by recent commit frequency. A function that is both hard to understand (high cyclomatic complexity) and actively changing is a higher priority than one that is complex but untouched. CC = cyclomatic complexity (independent execution paths); ND = max nesting depth; FO = fan-out (distinct callees).
Top 5 Hotspots
| Function | File | Risk | CC | ND | FO |
|---|---|---|---|---|---|
generatePlayground | scripts/generate-play.ts | 11.6 | 18 | 3 | 25 |
<anonymous> | scripts/actions/issue-pr.ts | 11.4 | 27 | 3 | 24 |
<anonymous> | scripts/actions/labeling.ts | 10.7 | 16 | 3 | 10 |
<anonymous> | scripts/actions/toggle-pr-with-issue.ts | 8.3 | 11 | 1 | 7 |
updateIndexREADME | scripts/readme.ts | 8.3 | 9 | 3 | 15 |
Hotspot Analysis
generatePlayground — scripts/generate-play.ts
Based on its name and location, generatePlayground likely orchestrates the construction of the TypeScript Playground links or sandbox environments associated with each challenge. This function hasn’t been touched in 271 days — it sits firmly in the debt quadrant, carrying structural complexity (CC 18, fan-out 25) that has accumulated across past development cycles without being addressed. Its 18 independent execution paths and 25 distinct callees mean that when this function is next changed, any mishandled branch can silently corrupt playground output across a wide surface. The god_function and long_function patterns flag it as a function that has absorbed responsibilities over time rather than delegating them — structural debt that warrants refactoring before the next development push.
Recommendation: Before any further changes, write characterization tests that capture current output for a representative set of challenges; then extract cohesive sub-functions (e.g. URL construction, file I/O, metadata formatting) to reduce the fan-out of 25 and bring CC below 10.
<anonymous> — scripts/actions/issue-pr.ts
An anonymous top-level function in scripts/actions/issue-pr.ts is almost certainly the main handler for the GitHub Actions workflow that manages issue and pull-request lifecycle events on the repo. At CC 27 — the highest cyclomatic complexity among all critical-band functions — it contains 27 independent decision paths, each representing a distinct scenario (new issue, closed PR, label change, etc.) that must be handled correctly and tested separately. This function hasn’t been touched in 326 days, placing it squarely in the debt quadrant: broadly coupled (fan-out 24) with structural complexity that has been stable for nearly a year. When it is next changed, any given commit will have 24 potential ripple points across already-fragile branching logic.
Recommendation: Decompose by event type: extract a dedicated handler function per GitHub event variant (issue opened, PR merged, etc.) so that each handler has a CC closer to 3–5 and the dispatch logic becomes a thin router; add integration tests against fixture payloads before splitting.
<anonymous> — scripts/actions/labeling.ts
The anonymous function in scripts/actions/labeling.ts is the likely entry point for automated label management on issues and PRs — assigning difficulty or status labels based on challenge metadata or contributor actions. Its CC of 16 and fan-out of 10 are lower than the issue-pr handler, and like its counterparts it hasn’t been touched in 326 days. The god_function pattern signals it is making decisions that could reasonably belong to separate, focused functions — and the stale_complex pattern confirms that complexity has been accumulating across multiple past change cycles without being addressed. This is structural debt that warrants refactoring before the automation layer is next developed.
Recommendation: Map the 10 fan-out callees and identify which ones relate to label lookup versus label mutation versus API calls; split these into distinct, testable units so that a change to label taxonomy does not require reasoning through the full 16-path decision tree.
Patterns Found
Antipatterns detected across the top functions in this snapshot:
| Pattern | Occurrences |
|---|---|
stale_complex | 4 |
god_function | 3 |
long_function | 2 |
These labels belong to two tiers — Tier 1 (structural): complex_branching, deeply_nested, exit_heavy, long_function, god_function. Tier 2 (relational/temporal): hub_function, cyclic_hub, middle_man, neighbor_risk, stale_complex, churn_magnet, shotgun_target, volatile_god.
Key Takeaways
- generatePlayground (scripts/generate-play.ts) carries a fan-out of 25 and CC 18, untouched for 271 days — write characterization tests before the next commit lands on it, or a regression may not surface until playground links break for challenge consumers.
- The anonymous handler in scripts/actions/issue-pr.ts has CC 27, the highest cyclomatic complexity in the critical band — that means 27 test cases are needed for full branch coverage; decomposing it by event type is the highest-leverage structural change available before the next development push on this layer.
- All three critical-band functions share the stale_complex pattern, meaning complexity has been accumulating across repeated past change cycles — adding a complexity budget (e.g. CC ≤ 10 enforced in CI) will prevent the next function from silently joining this tier when development resumes.
Reproduce This Analysis
git clone https://github.com/type-challenges/type-challenges
cd type-challenges
git checkout 0b0b0b18bcb7ac42dc22ce26ffb438231d4754b1
hotspots analyze . --mode snapshot --explain-patterns --force
To run the same analysis on your own codebase, run hotspots analyze . --mode snapshot in any local git repo — no configuration required.
Hotspots highlights structural and activity risk — not “bad code.” Findings are a prioritization aid, not a bug predictor. Editorial policy →