Use when refactoring fat Rails models with repetitive prefixes like entropy_*, notification_*, or multi-association coordination. Extracts PORO wrappers that group operations around nouns/concepts.
From vanilla-railsnpx claudepluginhub zemptime/zemptime-marketplace --plugin vanilla-railsThis skill uses the workspace's default tool permissions.
detecting.mdimplementing.mdDesigns and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Enables AI agents to execute x402 payments with per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents pay for APIs, services, or other agents.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Extract PORO wrappers that group 3+ operations around a noun/concept, keeping parent model focused.
Announce: "I'm using the writing-affordances skill to evaluate this for affordance extraction."
entropy_calculate, entropy_remind, entropy_cleanupassignments + watches + events)Don't use for: Single trait (use concern) | Single association (use extension) | 1-2 methods (use plain method)
Ask yourself:
notify(description) be clearer than notify(event)?entropy_* methods = Extract entropy affordance (prefix = noun)card.entropy.auto_clean_at vs card.entropy_auto_clean_atSee @detecting.md for complete decision framework.
| Pattern | Use When | Example | Key Question |
|---|---|---|---|
| Affordance | Group operations around noun | card.entropy.auto_clean_at | "Can I pass this around?" |
| Concern | Infrastructure or implicit behavior | Searchable (callbacks only) | "Does Rails call it implicitly?" |
| Concern + Affordance | Both infrastructure AND operations | Concern sets up associations, affordance provides API | "Need both?" |
| Association Ext | Single association operations | card.comments.recent | "Only touching one has_many?" |
Violating these = wrong pattern:
Card::Entropy.new(card), not new(card, user)entropy(as_of: date) should NOT use ||=# Before: Methods scattered in model or prefix smell
card.entropy_auto_clean_at
card.entropy_days_before_reminder
card.entropy_reminder_sent?
# After: Affordance
card.entropy.auto_clean_at
card.entropy.days_before_reminder
card.entropy.reminder_sent?
# Entry point in concern
module Card::Entropic
def entropy
Card::Entropy.for(self) # Factory pattern
end
def entropic?
entropy.present?
end
end
# PORO affordance class
class Card::Entropy
attr_reader :card, :auto_clean_period
class << self
def for(card)
return unless card.last_active_at
new(card, card.auto_postpone_period)
end
end
def initialize(card, auto_clean_period)
@card = card
@auto_clean_period = auto_clean_period
end
def auto_clean_at
card.last_active_at + auto_clean_period
end
def days_before_reminder
(auto_clean_period * 0.25).seconds.in_days.round
end
end
Non-obvious checks before completion: