.claude/skills/component-spec-extraction/SKILL.md
# Component Spec Extraction Use this skill when working with component specification extraction, SpecValue wrappers, or type-specific extraction patterns. ## Spec Class Locations **24 spec classes** organized in 4 packages: ### base/ Package (Core Specs) - `ComponentSpecs.java` - Base interface for all specs - `Spec.java` - Generic spec value holder - `SpecUnit.java` - Enum of measurement units - `SpecValue.java` - Type-safe unit-aware wrapper ### passive/ Package (Passive Components) - `Re
npx skillsauth add Cantara/lib-electronic-components .claude/skills/component-spec-extractionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when working with component specification extraction, SpecValue wrappers, or type-specific extraction patterns.
24 spec classes organized in 4 packages:
ComponentSpecs.java - Base interface for all specsSpec.java - Generic spec value holderSpecUnit.java - Enum of measurement unitsSpecValue.java - Type-safe unit-aware wrapperResistorSpecs.java - Resistance, tolerance, power ratingCapacitorSpecs.java - Capacitance, voltage, dielectric, ESRInductorSpecs.java - Inductance, current rating, DCRDiodeSpecs.java - Forward voltage, reverse voltage, currentTransistorSpecs.java - VCE, IC, hFE, polarityMosfetSpecs.java - VDS, ID, RDS(on), channel typeOpAmpSpecs.java - Configuration, GBW, input offsetVoltageRegulatorSpecs.java - Output voltage, current, dropoutPowerSupplySpecs.java - Input/output voltage, efficiencyBatterySpecs.java - Capacity, chemistry, voltageAdditional specs:
Purpose: Type-safe, unit-aware value representation.
Constructor (NO static factory method):
// ✅ CORRECT: Use constructor directly
SpecValue<Double> resistance = new SpecValue<>(1000.0, SpecUnit.OHM);
SpecValue<String> dielectric = new SpecValue<>("X7R", SpecUnit.NONE);
// ❌ WRONG: No factory method exists
// SpecValue<Double> resistance = SpecValue.of(1000.0, SpecUnit.OHM); // DOESN'T EXIST!
Implementation:
public class SpecValue<T> {
private final T value;
private final SpecUnit unit;
private final T minValue; // Optional range
private final T maxValue; // Optional range
// Constructor
public SpecValue(T value, SpecUnit unit) {
this.value = value;
this.unit = unit;
this.minValue = null;
this.maxValue = null;
}
// Constructor with range
public SpecValue(T value, SpecUnit unit, T minValue, T maxValue) {
this.value = value;
this.unit = unit;
this.minValue = minValue;
this.maxValue = maxValue;
}
public T getValue() { return value; }
public SpecUnit getUnit() { return unit; }
public T getMinValue() { return minValue; }
public T getMaxValue() { return maxValue; }
}
Examples:
// Resistance with tolerance
SpecValue<Double> resistance = new SpecValue<>(10000.0, SpecUnit.OHM, 9500.0, 10500.0);
// Capacitance
SpecValue<Double> capacitance = new SpecValue<>(100e-9, SpecUnit.FARAD); // 100nF
// Voltage rating
SpecValue<Double> voltage = new SpecValue<>(50.0, SpecUnit.VOLT);
// Dielectric (no unit)
SpecValue<String> dielectric = new SpecValue<>("X7R", SpecUnit.NONE);
Convention: Consistent camelCase method names across all files.
Patterns:
// ✅ CORRECT: extractXxx() pattern
public String extractResistance(String mpn);
public String extractCapacitance(String mpn);
public String extractVoltage(String mpn);
public String extractPackage(String mpn);
public String extractTolerance(String mpn);
public String extractDielectric(String mpn);
// ❌ WRONG: Inconsistent naming
public String getResistance(String mpn); // Don't mix get/extract
public String parseCapacitance(String mpn); // Don't use parse
public String resistance(String mpn); // Too terse
Rationale:
extract implies parsing from MPN stringget implies retrieving existing valueSpecUnit Enum Values:
public enum SpecUnit {
// Electrical
OHM("Ω"), // Resistance
FARAD("F"), // Capacitance
HENRY("H"), // Inductance
VOLT("V"), // Voltage
AMPERE("A"), // Current
WATT("W"), // Power
HERTZ("Hz"), // Frequency
// Dimensionless
PERCENTAGE("%"),
NONE("");
private final String symbol;
SpecUnit(String symbol) {
this.symbol = symbol;
}
public String getSymbol() {
return symbol;
}
}
Unit Conversion Patterns:
// Resistor values: k, M multipliers
"1k" → 1000.0 Ω
"10k" → 10000.0 Ω
"1M" → 1000000.0 Ω
// Capacitor values: p, n, u, m multipliers
"10pF" → 10e-12 F
"100nF" → 100e-9 F
"1uF" → 1e-6 F
"10mF" → 10e-3 F
// Voltage: m, k multipliers
"3.3V" → 3.3 V
"5V" → 5.0 V
"400kV" → 400000.0 V
Chip resistors (e.g., Yageo RC0805JR-0710KL):
public String extractResistance(String mpn) {
// RC0805JR-0710KL
// Positions 9-12: "10K" → 10kΩ
if (mpn.length() < 13) return "";
String valueCode = mpn.substring(9, 13); // "10KL"
// Parse "10K" → 10000Ω
}
Ceramic capacitors use 3-digit codes:
public String extractCapacitance(String mpn) {
// GRM188R71H104KA01D
// "104" in MPN → 10 × 10^4 pF = 100,000pF = 100nF
Pattern codePattern = Pattern.compile("(\\d{3})");
Matcher matcher = codePattern.matcher(mpn);
if (matcher.find()) {
String code = matcher.group(1);
int digit1 = code.charAt(0) - '0';
int digit2 = code.charAt(1) - '0';
int multiplier = code.charAt(2) - '0';
double picofarads = (digit1 * 10 + digit2) * Math.pow(10, multiplier);
return picofarads + "pF";
}
}
Examples:
Infineon IRFxxx series:
public String extractVoltage(String mpn) {
// IRF530 → 100V
// IRF540 → 100V
// IRFZ44 → 55V
// Known mappings for Infineon MOSFETs
if (mpn.startsWith("IRF530")) return "100V";
if (mpn.startsWith("IRF540")) return "100V";
if (mpn.startsWith("IRFZ44")) return "55V";
// Or parse from datasheet mapping table
}
Pattern 1: Return empty string (most common)
public String extractPackage(String mpn) {
if (mpn == null || mpn.isEmpty()) {
return ""; // Empty string indicates "not found"
}
// Extraction logic...
if (packageNotFound) {
return "";
}
return packageCode;
}
Pattern 2: Return null (for numeric values)
public Double extractCapacitance(String mpn) {
if (mpn == null) {
return null; // null indicates "not found"
}
// Extraction logic...
if (cannotParse) {
return null;
}
return capacitanceValue;
}
Pattern 3: Return Optional (modern approach)
public Optional<String> extractDielectric(String mpn) {
if (mpn == null) {
return Optional.empty();
}
// Extraction logic...
if (dielectricNotFound) {
return Optional.empty();
}
return Optional.of(dielectricType);
}
Recommendation: Use empty string for String returns, null for numeric returns.
public String extractResistance(String mpn) {
// ✅ CORRECT: Validate first
if (mpn == null || mpn.isEmpty()) {
return "";
}
if (mpn.length() < MINIMUM_LENGTH) {
return ""; // MPN too short to contain resistance code
}
// Now safe to extract
String valueCode = mpn.substring(startIndex, endIndex);
}
Metadata-driven similarity uses spec extraction:
// In ResistorSimilarityCalculator.calculateMetadataDrivenSimilarity():
// Extract resistance spec
String resistance1 = extractResistance(mpn1);
String resistance2 = extractResistance(mpn2);
if (!resistance1.isEmpty() && !resistance2.isEmpty()) {
// Create SpecValue
SpecValue<Double> r1 = new SpecValue<>(parseResistance(resistance1), SpecUnit.OHM);
SpecValue<Double> r2 = new SpecValue<>(parseResistance(resistance2), SpecUnit.OHM);
// Get tolerance rule from metadata
ComponentTypeMetadata.SpecConfig resistanceConfig = metadata.getSpecConfig("resistance");
ToleranceRule rule = resistanceConfig.getToleranceRule();
// Compare
double specScore = rule.compare(r1, r2);
double specWeight = profile.getEffectiveWeight(resistanceConfig.getImportance());
totalScore += specScore * specWeight;
}
Use new SpecValue<>(value, unit) constructor, not a factory method (doesn't exist).
All extraction methods use extractXxx() pattern. Don't mix with getXxx() or parseXxx().
10kΩ and 10000Ω are the same value but different strings. Always convert to base unit (Ω) before comparison.
Each manufacturer has unique MPN encoding. Resistor extraction for Yageo differs from Vishay, KOA, etc.
/similarity-metadata - How specs are used in metadata-driven similarity/metadata-driven-similarity-conversion - Converting calculators to use spec extractionSpecValue.java - Type-safe wrapper implementationSpecUnit.java - Measurement units enumdata-ai
Cost-effective task delegation strategy using Haiku model for straightforward work. Use when planning how to approach simple, pattern-following tasks to minimize costs.
tools
Use when working with component similarity calculations - comparing MPNs, finding equivalent parts, implementing new similarity calculators, or understanding how component matching works.
testing
Use when working with transistor similarity calculations - comparing BJT MPNs, understanding NPN/PNP polarity matching, equivalent groups like 2N2222/PN2222, or transistor-specific similarity logic.
testing
Use when working with sensor similarity calculations - comparing temperature/accelerometer/humidity sensor MPNs, understanding sensor families, equivalent parts, or sensor-specific similarity logic.