with one click
ln-645-open-source-replacer
// Discovers custom modules replaceable by OSS, evaluates alternatives (stars, license, CVE), generates migration plan. Use when reducing custom code.
// Discovers custom modules replaceable by OSS, evaluates alternatives (stars, license, CVE), generates migration plan. Use when reducing custom code.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | ln-645-open-source-replacer |
| description | Discovers custom modules replaceable by OSS, evaluates alternatives (stars, license, CVE), generates migration plan. Use when reducing custom code. |
| allowed-tools | Read, Grep, Glob, Bash, WebFetch, WebSearch, mcp__Ref, mcp__context7, mcp__hex-graph__find_references, mcp__hex-graph__analyze_architecture, mcp__hex-line__read_file, mcp__hex-line__grep_search, mcp__hex-line__outline |
| license | MIT |
Paths: File paths (
references/,../ln-*) are relative to this skill directory.
Type: L3 Worker
L3 Worker that discovers custom modules, analyzes their purpose, and finds battle-tested open-source replacements via MCP Research.
Out of Scope:
- codebase_root: string # Project root
- tech_stack: object # Language, framework, package manager, existing dependencies
- output_dir: string # e.g., ".hex-skills/runtime-artifacts/runs/{run_id}/audit-report"
# Domain-aware (optional, from coordinator)
- domain_mode: "global" | "domain-aware" # Default: "global"
- current_domain: string # e.g., "users", "billing" (only if domain-aware)
- scan_path: string # e.g., "src/users/" (only if domain-aware)
Detection policy: use two-layer detection (candidate scan, then context verification); load references/two_layer_detection.md only when the verification method is ambiguous.
Tool policy: follow host AGENTS.md MCP preferences; load references/mcp_tool_preferences.md and references/mcp_integration_patterns.md only when host policy is absent or MCP behavior is unclear.
Use hex-graph first when architecture or cross-file references materially improve module discovery. Use hex-line first for local code reads when available. If MCP is unavailable, unsupported, or not indexed, continue with built-in Read/Grep/Glob/Bash and state the fallback in the report.
scan_root = scan_path IF domain_mode == "domain-aware" ELSE codebase_root
# Step 1: Find significant custom files
candidates = []
FOR EACH file IN Glob("**/*.{ts,js,py,rb,go,java,cs}", root=scan_root):
IF file in node_modules/ OR vendor/ OR .venv/ OR dist/ OR build/ OR test/ OR __test__/:
SKIP
line_count = wc -l {file}
IF line_count >= 100:
candidates.append(file)
# Step 2: Filter to utility/library-like modules
utility_paths = ["utils/", "lib/", "helpers/", "common/", "shared/", "pkg/", "internal/"]
name_patterns = ["parser", "formatter", "validator", "converter", "encoder",
"decoder", "serializer", "logger", "cache", "queue", "scheduler",
"mailer", "http", "client", "wrapper", "adapter", "connector",
"transformer", "mapper", "builder", "factory", "handler"]
modules = []
FOR EACH file IN candidates:
is_utility_path = any(p in file.lower() for p in utility_paths)
is_utility_name = any(p in basename(file).lower() for p in name_patterns)
export_count = count_exports(file) # Grep for export/module.exports/def/class
IF is_utility_path OR is_utility_name OR export_count > 5:
modules.append(file)
# Step 3: Pre-classification gate
FOR EACH module IN modules:
# Read first 30 lines to classify
header = Read(module, limit=30)
classify as:
- "utility": generic reusable logic (validation, parsing, formatting, HTTP, caching)
- "integration": wrappers around external services (email, payments, storage)
- "domain-specific": business logic unique to project (scoring, routing, pricing rules)
IF classification == "domain-specific":
no_replacement_found.append({module, reason: "Domain-specific business logic"})
REMOVE from modules
# Cap: analyze max 15 utility/integration modules per invocation
modules = modules[:15]
FOR EACH module IN modules:
# Read code (first 200 lines + exports summary)
code = Read(module, limit=200)
exports = Grep("export|module\.exports|def |class |func ", module)
# Extract goal: what problem does this module solve?
goal = {
domain: "email validation" | "HTTP retry" | "CSV parsing" | ...,
inputs: [types],
outputs: [types],
key_operations: ["validates email format", "checks MX records", ...],
complexity_indicators: ["regex", "network calls", "state machine", "crypto", ...],
summary: "Custom email validator with MX record checking and disposable domain filtering"
}
FOR EACH module WHERE module.goal extracted:
# Strategy 1: WebSearch (primary)
WebSearch("{goal.domain} {tech_stack.language} library package 2026")
WebSearch("{goal.summary} open source alternative {tech_stack.language}")
# Strategy 2: Context7 (for known ecosystems)
IF tech_stack.package_manager == "npm":
WebSearch("{goal.domain} npm package weekly downloads")
IF tech_stack.package_manager == "pip":
WebSearch("{goal.domain} python library pypi")
# Strategy 3: Ref (documentation search)
ref_search_documentation("{goal.domain} {tech_stack.language} recommended library")
# Strategy 4: Ecosystem alignment -- check if existing project dependencies
# already cover this goal (e.g., project uses Zod -> check zod plugins first)
FOR EACH dep IN tech_stack.existing_dependencies:
IF dep.ecosystem overlaps goal.domain:
WebSearch("{dep.name} {goal.domain} plugin extension")
# Collect candidates (max 5 per module)
alternatives = top_5_by_relevance(search_results)
MANDATORY: Security Gate and License Classification run for EVERY candidate before confidence assignment.
FOR EACH module, FOR EACH alternative:
# 4a. Basic info
info = {
name: "zod" | "email-validator" | ...,
version: "latest stable",
weekly_downloads: N,
github_stars: N,
last_commit: "YYYY-MM-DD",
}
# 4b. Security Gate (mandatory)
WebSearch("{alternative.name} CVE vulnerability security advisory")
IF unpatched HIGH/CRITICAL CVE found:
security_status = "VULNERABLE"
-> Cap confidence at LOW, add warning to Findings
ELIF patched CVE (older version):
security_status = "PATCHED_CVE"
-> Note in report, no confidence cap
ELSE:
security_status = "CLEAN"
# 4c. License Classification
license = detect_license(alternative)
IF license IN ["MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC", "Unlicense"]:
license_class = "PERMISSIVE"
ELIF license IN ["GPL-2.0", "GPL-3.0", "AGPL-3.0", "LGPL-2.1", "LGPL-3.0"]:
IF project_license is copyleft AND compatible:
license_class = "COPYLEFT_COMPATIBLE"
ELSE:
license_class = "COPYLEFT_INCOMPATIBLE"
ELSE:
license_class = "UNKNOWN"
# 4d. Ecosystem Alignment
ecosystem_match = alternative.name IN tech_stack.existing_dependencies
OR alternative.ecosystem == tech_stack.framework
# Prefer: zod plugin over standalone if project uses zod
# 4e. Feature & API Evaluation
api_surface_match = HIGH | MEDIUM | LOW
feature_coverage = percentage # what % of custom module features covered
migration_effort = S | M | L # S=<4h, M=4-16h, L=>16h
# 4f. Confidence Assignment
# HIGH: >10k stars, active (commit <6mo), >90% coverage,
# PERMISSIVE license, CLEAN security, ecosystem_match preferred
# MEDIUM: >1k stars, maintained (commit <1yr), >70% coverage,
# PERMISSIVE license, no unpatched CRITICAL CVEs
# LOW: <1k stars OR unmaintained OR <70% coverage
# OR COPYLEFT_INCOMPATIBLE OR VULNERABLE
MANDATORY READ: Load references/audit_worker_core_contract.md and references/templates/audit_worker_report_template.md.
Write JSON summary per references/audit_summary_contract.md. In managed mode the caller passes both runId and summaryArtifactPath; in standalone mode the worker generates its own run-scoped artifact path per shared contract.
Build report in memory, write to {output_dir}/645-open-source-replacer[-{domain}].md.
# Open Source Replacement Audit Report
<!-- AUDIT-META
worker: ln-645
category: Open Source Replacement
domain: {domain_name|global}
scan_path: {scan_path|.}
score: {X.X}
total_issues: {N}
critical: 0
high: {N}
medium: {N}
low: {N}
status: completed
-->
## Checks
| ID | Check | Status | Details |
|----|-------|--------|---------|
| module_discovery | Module Discovery | passed/warning | Found N modules >= 100 LOC |
| classification | Pre-Classification | passed | N utility, M integration, K domain-specific (excluded) |
| goal_extraction | Goal Extraction | passed/warning | Extracted goals for N/M modules |
| alternative_search | Alternative Search | passed/warning | Found alternatives for N modules |
| security_gate | Security Gate | passed/warning | N candidates checked, M clean, K vulnerable |
| evaluation | Replacement Evaluation | passed/failed | N HIGH confidence, M MEDIUM |
| migration_plan | Migration Plan | passed/skipped | Generated for N replacements |
## Findings
| Severity | Location | Issue | Principle | Recommendation | Effort |
|----------|----------|-------|-----------|----------------|--------|
| HIGH | src/utils/email-validator.ts (245 LOC) | Custom email validation with MX checking | Reuse / OSS Available | Replace with zod + zod-email (28k stars, MIT, 95% coverage) | M |
## Migration Plan
| Priority | Module | Lines | Replacement | Confidence | Effort | Steps |
|----------|--------|-------|-------------|------------|--------|-------|
| 1 | src/utils/email-validator.ts | 245 | zod + zod-email | HIGH | M | 1. Install 2. Create schema 3. Replace calls 4. Remove module 5. Test |
<!-- DATA-EXTENDED
{
"modules_scanned": 15,
"modules_with_alternatives": 8,
"reuse_opportunity_score": 6.5,
"replacements": [
{
"module": "src/utils/email-validator.ts",
"lines": 245,
"classification": "utility",
"goal": "Email validation with MX checking",
"alternative": "zod + zod-email",
"confidence": "HIGH",
"stars": 28000,
"last_commit": "2026-02-10",
"license": "MIT",
"license_class": "PERMISSIVE",
"security_status": "CLEAN",
"ecosystem_match": true,
"feature_coverage": 95,
"effort": "M",
"migration_steps": ["Install zod + zod-email", "Create validation schema", "Replace validate() calls", "Remove custom module", "Run tests"]
}
],
"no_replacement_found": [
{"module": "src/lib/domain-scorer.ts", "reason": "Domain-specific business logic", "classification": "domain-specific"}
]
}
-->
Report written: .hex-skills/runtime-artifacts/runs/{run_id}/audit-report/645-open-source-replacer[-{domain}].md
Score: X.X/10 | Issues: N (C:0 H:N M:N L:N)
Uses standard penalty formula from references/audit_scoring.md:
penalty = (critical x 2.0) + (high x 1.0) + (medium x 0.5) + (low x 0.2)
score = max(0, 10 - penalty)
Severity mapping:
Apply the already-loaded references/audit_worker_core_contract.md.
Apply the already-loaded references/audit_worker_core_contract.md.
{output_dir}/645-open-source-replacer[-{domain}].mdreferences/audit_scoring.mdreferences/research_tool_fallback.mdVersion: 1.0.0 Last Updated: 2026-02-26