sergdort/combinefeedback/combinefeedback-state-machines
Claude Code and agent skill by sergdort/combinefeedback
- community
Checking that the SKILL.md file is still in the repository.
Use whenever building, changing, or reviewing app logic that uses the CombineFeedback Swift library.
Install
npx vskill@latest install sergdort/combinefeedback/combinefeedback-state-machinesSKILL.md
CombineFeedback State Machines
Use this skill when designing or refining application logic built with the Swift CombineFeedback library. Focus on modeling state machines: state boundaries, events, reducers, feedback lifecycles, and reusable child machines.
This skill is for agents helping library consumers. Do not assume access to the CombineFeedback source repository. Respect the user's app architecture, existing agent instructions, and any state machines already defined in the app.
Scope
Use this skill for:
- Designing a new CombineFeedback feature state machine.
- Splitting a large state machine into smaller machines.
- Refactoring recurring lifecycle behavior into reusable child machines.
- Choosing between
OnEvent,OnChange,SideEffect, andFeedback.custom. - Producing a machine decomposition sketch and transition/invariant contract.
Do not use this skill for:
- SwiftUI/store binding guidance.
- Testing strategy or test-store patterns (use the companion skill
combinefeedback-state-machine-testing).
- Generic finite-state-machine theory unrelated to CombineFeedback.
If the user is exploring or refactoring, proactively challenge state boundaries and look for reusable lifecycle machines. If the user is already implementing an agreed plan, do not reopen architecture unless the plan conflicts with CombineFeedback's model.
Verify Before Compile-Ready Code
CombineFeedback APIs may vary by installed version. Before producing compile-ready code in a consumer app, inspect the local package version, docs, or source if available. For design sketches, use current CombineFeedback vocabulary but keep snippets conceptual when version details are uncertain.
Current primitives to expect:
StateMachine: composes reducers and feedbacks into a behavior.State: the single source of truth for the machine.Event: external inputs and feedback-produced occurrences.Reducer: pure state transition logic, usually(inout State, Event) -> Void.Feedback: observes state/event streams and emits events.OnChange: runs latest/cancellable effects from changes in derived state.OnEvent: runs latest effects from a specific event stream.SideEffect: fire-and-forget async work that does not emit events.Feedback.custom: escape hatch for advanced stream or cancellation behavior.ScopeandIfLet: compose child machines into parent machines.
In CombineFeedback, reducers mutate state only; feedbacks observe state/events and emit events back into the loop.
Design Workflow
When asked to design or improve a CombineFeedback machine, work in this order:
- Identify the behavior boundary.
- Separate recurring lifecycle behavior from feature-specific policy.
- Choose
Stateshape using enums for exclusive modes and structs for
orthogonal facts.
- Name public
Eventcases for user intent, external input, and effect results. - Put all state transitions in reducers.
- Decide which feedback primitive owns each effect lifecycle.
- Compose reusable child machines with explicit child state and child event cases.
- End with a decomposition sketch and a lightweight transition/invariant
contract.
Do not require broad repository reconnaissance. Use the context already provided by the user. Inspect targeted files only when needed to avoid inventing APIs, duplicating an existing reusable machine, or violating local naming/style.
Modeling Rules
Events Trigger Intent, State Owns Lifecycle
Use OnEvent when an effect is a direct reaction to an external event and the effect's lifetime is tied only to that event stream.
Use reducer -> lifecycle/request state -> OnChange when the system must start, cancel, or replace work as state changes. This is the default for loading, pagination, validation, polling, retry, and debounced search lifecycles.
Examples:
- A button tap that should fire analytics:
SideEffect. - A one-off event-local async command:
OnEvent. - A fetch that should cancel when leaving
.fetching: reducer sets state,
OnChange observes derived request state.
- A polling loop that starts on appear and stops on disappear: reducer sets a
polling mode, OnChange observes that mode.
Make Impossible States Unrepresentable
Use sum types for mutually exclusive lifecycle modes:
Avoid modeling one lifecycle as independent isLoading, value?, error?, and request? fields. Those combinations create invalid states the reducer must defend manually.
Use product types for facts that can coexist:
Do not store values that can be derived from state. Derive request state from the mode that owns it:
Prefer Reusable Machines For Recurring Lifecycle Behavior
Reusable child machines are a good fit for behavior like:
- Fetching one resource.
- Pagination.
- Username or form-field validation.
- Debounced search.
- Polling.
- Retry/backoff lifecycle.
Keep one-off feature policy local to the feature. Do not extract a reusable machine if its public API would leak parent-specific concepts or create more glue than clarity.
Reusable child machines should own their lifecycle policy and the effect needed to fulfill it. Inject dependencies through the machine initializer:
The parent supplies concrete services when composing the child.
Compose Child Machines Explicitly
When a parent owns a reusable child machine, expose child state and child events explicitly so Scope can route them:
Parent-specific events can still translate into child events when that is the clearest domain API, but do not manually duplicate child lifecycle state in the parent.
Choosing Feedback Primitives
Use this decision rule:
OnChange: state-driven lifecycle. Entering a state starts work; leaving or
changing the derived request cancels/replaces work.
OnEvent: direct reaction to an event stream. Good for external triggers when
no durable lifecycle state needs to own cancellation.
SideEffect: fire-and-forget work that cannot emit events, such as analytics
or logging.
Feedback.custom: advanced stream coordination not expressible with
OnChange, OnEvent, or SideEffect.
Prefer OnChange for effect lifecycles that are part of the state machine's meaning. Prefer OnEvent only when modeling the effect as durable state would be artificial.
Canonical Concept: Fetch
Use Fetch as the canonical reusable lifecycle example. This is conceptual Swift-like pseudo-code, not a drop-in generic implementation.
Important modeling points:
.fetch(params)is still an event. Events express public intent..fetching(params)is lifecycle state. State owns whether work should exist.requestis derived, not stored separately.OnChangegives latest/cancellation behavior whenrequestchanges or becomes
nil.
.cancelcancels by moving state to a mode whose derived request isnil.- Stale response handling can be added with request identity if the local effect
source is non-cooperative or can emit after cancellation, but do not make that complexity the default V1 pattern.
Required Output Shape
When this skill is used for design work, end with a concise design sketch that contains these sections.
Machine Decomposition
List each machine and its ownership:
State Shape
Show the proposed state structure and call out which parts are exclusive modes versus orthogonal facts.
Event Contract
List public intent events, child events, and feedback result events. Prefer literal domain names for user/external events and clear result names for effect outputs.
Feedback Plan
For each effect, state which primitive owns it and why:
Transition And Invariant Contract
Use a lightweight contract, not a huge table:
Open Modeling Questions
Ask only questions that affect the state machine boundary or lifecycle, such as:
- Should success data remain visible while refreshing?
- Should cancellation return to
.idleor preserve previous content? - Is pagination a separate child machine or part of the screen's domain policy?
- Can the effect source emit after cancellation, requiring request identity?
Model-Level Traps To Avoid
Avoid warnings that the API already prevents. Focus on traps the type system and library cannot fully prevent:
- Boolean/optional soup for a lifecycle that should be an enum.
- Stored request flags that duplicate derived state.
OnEventfor work that must cancel when state leaves a mode.- Reusable machines that leak parent-specific policy.
- Giant screen machines that hide recurring lifecycle submachines.
- Reopening architecture when the user has already supplied an agreed plan.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/combinefeedback-state-machines/SKILL.md
Popularity
- Repository stars
- 686
- Repository forks
- 53
- 7-day trend score
- 33
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/sergdort/combinefeedback/combinefeedback-state-machines)