Autogenerate formula implementations from formula specifications (F-*). Converts mathematical formulas, calculations, and algorithms into production code with tests. Use when F-* includes formula specifications.
/plugin marketplace add foolishimp/ai_sdlc_method/plugin install aisdlc-methodology@aisdlcThis skill is limited to using the following tools:
Skill Type: Actuator (Code Generation) Purpose: Generate formula implementations from F-* specifications Prerequisites:
You are autogenerating formulas from formula specifications.
Your goal is to transform structured F- formulas* into calculation functions with tests.
Input:
F-001: Stripe fee calculation
Formula: fee = (amount * 0.029) + 0.30
Inputs: amount (float)
Output: fee (float, rounded to 2 decimals)
Generated:
# Generated from: F-001
STRIPE_PERCENTAGE_FEE = 0.029 # 2.9%
STRIPE_FIXED_FEE = 0.30 # $0.30
def calculate_stripe_fee(amount: float) -> float:
"""
Calculate Stripe processing fee.
Generated from: F-001 (Stripe fee calculation)
Formula: fee = (amount * 0.029) + 0.30
Args:
amount: Payment amount in dollars
Returns:
Processing fee in dollars (rounded to 2 decimals)
Examples:
>>> calculate_stripe_fee(100.00)
3.20
>>> calculate_stripe_fee(1000.00)
29.30
"""
# Implements: F-001
fee = (amount * STRIPE_PERCENTAGE_FEE) + STRIPE_FIXED_FEE
return round(fee, 2)
# Generated tests
def test_calculate_stripe_fee_100_dollars():
assert calculate_stripe_fee(100.00) == 3.20
def test_calculate_stripe_fee_1000_dollars():
assert calculate_stripe_fee(1000.00) == 29.30
def test_calculate_stripe_fee_minimum_charge():
# For $0.01, fee is still $0.30 fixed + 0.0003% ≈ $0.30
assert calculate_stripe_fee(0.01) == 0.30
Input:
F-002: Password reset token expiry
Formula: expiry_time = issue_time + (60 * 60) seconds
Inputs: issue_time (datetime)
Output: expiry_time (datetime)
Generated:
# Generated from: F-002
from datetime import datetime, timedelta
TOKEN_EXPIRY_SECONDS = 60 * 60 # 1 hour
def calculate_token_expiry(issue_time: datetime) -> datetime:
"""
Calculate password reset token expiry time.
Generated from: F-002 (Token expiry calculation)
Formula: expiry_time = issue_time + 3600 seconds
Args:
issue_time: When token was issued
Returns:
Expiry time (1 hour after issue)
Examples:
>>> issue = datetime(2025, 11, 20, 10, 0, 0)
>>> expiry = calculate_token_expiry(issue)
>>> expiry
datetime(2025, 11, 20, 11, 0, 0)
"""
# Implements: F-002
return issue_time + timedelta(seconds=TOKEN_EXPIRY_SECONDS)
# Generated tests
def test_token_expiry_one_hour():
issue = datetime(2025, 11, 20, 10, 0, 0)
expiry = calculate_token_expiry(issue)
assert expiry == datetime(2025, 11, 20, 11, 0, 0)
def test_token_expiry_across_day_boundary():
issue = datetime(2025, 11, 20, 23, 30, 0)
expiry = calculate_token_expiry(issue)
assert expiry == datetime(2025, 11, 21, 0, 30, 0)
Input:
F-010: Compound interest
Formula: A = P(1 + r/n)^(nt)
Inputs:
- P: principal amount
- r: annual interest rate (decimal)
- n: compounding frequency (times per year)
- t: time in years
Output: A (final amount, rounded to 2 decimals)
Generated:
# Generated from: F-010
import math
def calculate_compound_interest(
principal: float,
rate: float,
compounding_frequency: int,
years: float
) -> float:
"""
Calculate compound interest.
Generated from: F-010 (Compound interest formula)
Formula: A = P(1 + r/n)^(nt)
Args:
principal: Initial principal amount
rate: Annual interest rate (decimal, e.g., 0.05 for 5%)
compounding_frequency: Times compounded per year (e.g., 12 for monthly)
years: Time period in years
Returns:
Final amount (rounded to 2 decimals)
Examples:
>>> calculate_compound_interest(1000, 0.05, 12, 1)
1051.16
>>> calculate_compound_interest(1000, 0.05, 1, 5)
1276.28
"""
# Implements: F-010
amount = principal * math.pow(
1 + (rate / compounding_frequency),
compounding_frequency * years
)
return round(amount, 2)
# Generated tests
def test_compound_interest_monthly_one_year():
# $1000 at 5% compounded monthly for 1 year
result = calculate_compound_interest(1000, 0.05, 12, 1)
assert result == 1051.16
def test_compound_interest_annually_five_years():
# $1000 at 5% compounded annually for 5 years
result = calculate_compound_interest(1000, 0.05, 1, 5)
assert result == 1276.28
Input:
F-020: Discount calculation
Formula: discounted_price = original_price * (1 - discount_percentage)
Inputs:
- original_price: float
- discount_percentage: float (0.0 to 1.0)
Output: discounted_price (float, rounded to 2 decimals)
Constraints: discount_percentage must be 0.0 to 1.0
Generated:
# Generated from: F-020
def calculate_discounted_price(original_price: float, discount_percentage: float) -> float:
"""
Calculate discounted price.
Generated from: F-020 (Discount calculation)
Formula: discounted_price = original_price * (1 - discount_percentage)
Args:
original_price: Original price before discount
discount_percentage: Discount as decimal (0.0 to 1.0)
Returns:
Discounted price (rounded to 2 decimals)
Raises:
ValueError: If discount_percentage not in range [0.0, 1.0]
Examples:
>>> calculate_discounted_price(100.00, 0.20)
80.00
>>> calculate_discounted_price(50.00, 0.50)
25.00
"""
# Implements: F-020
# Constraint: discount_percentage must be 0.0 to 1.0
if not 0.0 <= discount_percentage <= 1.0:
raise ValueError("Discount percentage must be between 0.0 and 1.0")
discounted = original_price * (1 - discount_percentage)
return round(discounted, 2)
# Generated tests
def test_discount_20_percent():
assert calculate_discounted_price(100.00, 0.20) == 80.00
def test_discount_50_percent():
assert calculate_discounted_price(50.00, 0.50) == 25.00
def test_discount_0_percent():
assert calculate_discounted_price(100.00, 0.00) == 100.00
def test_discount_100_percent():
assert calculate_discounted_price(100.00, 1.00) == 0.00
def test_discount_invalid_negative():
with pytest.raises(ValueError):
calculate_discounted_price(100.00, -0.10)
def test_discount_invalid_over_100():
with pytest.raises(ValueError):
calculate_discounted_price(100.00, 1.50)
Input:
F-030: Idempotency key generation
Formula: key = SHA256(merchant_id + timestamp + amount + card_last4)
Inputs:
- merchant_id: string
- timestamp: int (unix timestamp)
- amount: float
- card_last4: string (last 4 digits)
Output: key (hex string)
Generated:
# Generated from: F-030
import hashlib
def generate_idempotency_key(
merchant_id: str,
timestamp: int,
amount: float,
card_last4: str
) -> str:
"""
Generate idempotency key for payment.
Generated from: F-030 (Idempotency key generation)
Formula: SHA256(merchant_id + timestamp + amount + card_last4)
Args:
merchant_id: Merchant identifier
timestamp: Unix timestamp
amount: Payment amount
card_last4: Last 4 digits of card
Returns:
SHA256 hex digest as idempotency key
Examples:
>>> key = generate_idempotency_key("merch_123", 1637000000, 100.00, "4242")
>>> len(key)
64
"""
# Implements: F-030
data = f"{merchant_id}{timestamp}{amount}{card_last4}"
return hashlib.sha256(data.encode()).hexdigest()
# Generated tests
def test_idempotency_key_deterministic():
# Same inputs → same key
key1 = generate_idempotency_key("merch_123", 1637000000, 100.00, "4242")
key2 = generate_idempotency_key("merch_123", 1637000000, 100.00, "4242")
assert key1 == key2
def test_idempotency_key_different_timestamp():
# Different timestamp → different key
key1 = generate_idempotency_key("merch_123", 1637000000, 100.00, "4242")
key2 = generate_idempotency_key("merch_123", 1637000001, 100.00, "4242")
assert key1 != key2
def test_idempotency_key_length():
key = generate_idempotency_key("merch_123", 1637000000, 100.00, "4242")
assert len(key) == 64 # SHA256 hex = 64 chars
Input:
F-040: Temperature conversion
Formula: celsius = (fahrenheit - 32) * 5/9
Inputs: fahrenheit (float)
Output: celsius (float, rounded to 1 decimal)
Generated:
# Generated from: F-040
def fahrenheit_to_celsius(fahrenheit: float) -> float:
"""
Convert Fahrenheit to Celsius.
Generated from: F-040 (Temperature conversion)
Formula: celsius = (fahrenheit - 32) * 5/9
Args:
fahrenheit: Temperature in Fahrenheit
Returns:
Temperature in Celsius (rounded to 1 decimal)
Examples:
>>> fahrenheit_to_celsius(32.0)
0.0
>>> fahrenheit_to_celsius(212.0)
100.0
>>> fahrenheit_to_celsius(98.6)
37.0
"""
# Implements: F-040
celsius = (fahrenheit - 32) * 5 / 9
return round(celsius, 1)
# Generated tests
def test_fahrenheit_to_celsius_freezing():
assert fahrenheit_to_celsius(32.0) == 0.0
def test_fahrenheit_to_celsius_boiling():
assert fahrenheit_to_celsius(212.0) == 100.0
def test_fahrenheit_to_celsius_body_temp():
assert fahrenheit_to_celsius(98.6) == 37.0
For every formula, generate:
f(f_inv(x)) == x[FORMULA GENERATION]
Input: 5 formulas
Generated Formulas:
✓ calculate_stripe_fee() from F-001
✓ calculate_token_expiry() from F-002
✓ generate_idempotency_key() from F-030
✓ calculate_compound_interest() from F-010
✓ fahrenheit_to_celsius() from F-040
Generated Constants:
✓ STRIPE_PERCENTAGE_FEE = 0.029
✓ STRIPE_FIXED_FEE = 0.30
✓ TOKEN_EXPIRY_SECONDS = 3600
Generated Tests:
✓ 20 tests (5 formulas × 4 tests average)
Running tests...
✓ All 20 tests PASSING
Files:
+ src/calculations.py (5 formulas, 145 lines)
+ tests/test_calculations.py (20 tests, 127 lines)
Before invoking this skill, ensure:
If F-* too vague:
Why autogenerate formulas?
Formula complexity handling:
Homeostasis Goal:
desired_state:
all_formulas_have_code: true
all_formula_code_has_tests: true
all_tests_passing: true
formulas_documented: true
"Excellence or nothing" 🔥
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.