---
name: applicaster-preference-selector
description: "Preference Selector integration: use when building, reviewing, or hardening a cross-platform Zapp selector for content preferences, UI language, push topics, or ordered multi-action settings. Establishes the selector contract before edits, chooses documented roles or actions, validates feeds against a versioned per-selector contract, and provides Zapp configuration and device verification steps."
---

# Applicaster Preference Selector

Build or harden a **Preference Selector** feed and its Zapp integration. A selector is a
cross-platform user decision that either records state or performs one supported immediate
action. Its contract is the approved agreement between the product flow, feed, state owner,
Zapp configuration, and downstream consumer. Establish and approve that contract before
editing.

Use this skill for content/configuration preferences, UI-language selection, push-topic
subscription selection, and composite selectors that need ordered actions. It supports static
feeds, Pipes/DSP feeds, and existing backend endpoints. It does not create a new backend or
mutate Zapp Studio.

## Non-Negotiable Gates

1. Ask one decision at a time. Discover facts from the target project and current Applicaster
   documentation; do not ask the developer for facts the environment can establish.
2. For every stateful selector, record its cardinality, stable tags, authority, state shape,
   `current_selection` hydration source, and downstream consumer before edits. A one-shot
   selector must be explicitly classified as such.
3. Default to cross-platform parity. A different platform flow requires an approved matrix
   naming each difference, its rationale, and its acceptance check.
4. Prefer a documented role when it fully expresses the behavior. Use `tap_actions.actions`
   only for multiple ordered effects, confirmation, or behavior a role cannot express. A
   UI-language change uses `setUILanguage` then `appRestart`. Never overlap role and action
   writes for the same state.
5. Every selector screen uses a List or Grid with a selected cell state. `current_selection`
   reads from exactly one source — never both: the `@{ctx/<key>}` storage token (device-local,
   instant toggle) or an inline value/array the backend bakes into the feed (cross-device,
   server truth). Content-affecting selectors define their unselected fallback and their
   supported update mechanism. For remote authority, a feed refresh (`refreshComponent` in the
   tap chain, or Zapp refresh configuration) re-hydrates the inline value after a tap — eventual,
   not instant; use `appRestart` only when required. Instant feedback and cross-device highlight
   together are not expressible from the feed alone: they require a client-side action plugin
   that owns the state (optimistic toggle, then server reconcile).
6. Remote state requires an approved Zapp Endpoint/CloudEvent contract, secure transport,
   context/identity binding, read-back source, and concurrency rule. Do not claim rollback,
   retry, or offline behavior unless the documented platform contract supports it.
7. Every deployable selector has a versioned contract file and passes the skill-local
   [validator](tools/preference-selector-e2e/README.md). Device verification remains required
   because the validator cannot render native selected states or execute native actions.
8. Do not edit until the developer explicitly approves the implementation contract. Do not
   report completion without `## Zapp Configuration` and the verification result or blocker.

## 1. Establish Facts

1. Fetch the current Preference Selector, feeds, actions, roles, context-key, and relevant
   downstream feature documentation. Read [the feature contract](references/preference-selector-contract.md)
   alongside it and reconcile drift toward current documentation.
2. Inspect the target project without asking: existing feed-hosting surface, feed conventions,
   context and endpoint conventions, layout/components, selected-cell styles, downstream
   consumers, authentication, test/build commands, and deployment URL shape. Search for
   existing preference, language, notification-topic, `localStorageSet`, `sendCloudEvent`,
   `setUILanguage`, and `appRestart` implementations.
3. If live documentation cannot be fetched, name the unavailable source and ask whether to
   proceed from the bundled reference. Do not silently treat it as current.

Completion: the available delivery surface and verified platform constraints are evidenced by
the code and current documentation.

## 2. Resolve Decisions

Present a concise sourced fact summary. Ask only applicable questions, one at a time, with the
constraint, recommended answer, and consequence of choosing otherwise. Use
[decision guidance](references/decision-guidance.md) for the complete branch rules.

Resolve in this dependency order:

1. Classify the selector as **one-shot** or **stateful**.
2. Name one semantic domain and outcome: preference, language, push topic, or composite action.
3. For stateful selectors, choose `single` or `multi` selection and whether empty selection is
   valid.
4. Establish catalog ownership, stable machine tags, and the preference-data contract.
5. Choose local, remote, or combined authority. Define `current_selection` from the
   authoritative read path.
6. For remote authority, resolve the Zapp Endpoint/CloudEvent, identity, data minimization,
   HTTPS/configuration, read-back, and multi-device concurrency rule.
7. Apply the role/action rule. For actions, approve their order, confirmation/cancel behavior,
   and only documented failure semantics.
8. Name the downstream consumer, unselected/default behavior, and either Zapp refresh
   configuration or `appRestart`. Prefer refresh when it applies correctly.
9. For language, map UI language separately from content locale and require `appRestart`. For
   push topics, map topic derivation and consent/permission behavior.
10. Define entry and re-entry flow, List/Grid presentation, selected state,
    localization/accessibility, and any platform-deviation matrix.
11. Confirm dynamic-feed unavailable behavior, feed host, contract-file path, optional
    server-side analytics, documentation, and verification inputs.

The feature does not own client-SDK offline behavior or built-in SDK analytics. Address reset
or clear behavior only when current documentation or the selected product flow requires it.

Completion: every applicable product decision has a recorded developer answer.

## 3. Confirm Before Edits

Present a short implementation contract containing:

- Outcome, semantic domain, one-shot/stateful classification, selection mode, catalog owner,
  stable tags, and data shape.
- Authority, key, read/write paths, `current_selection`, remote Endpoint/CloudEvent and
  identity details when applicable.
- Role or ordered action chain, confirmation behavior, and selected update mechanism.
- Downstream consumer, unselected fallback, entry/re-entry flow, layout/selected style, and
  any platform deviations.
- Feed-hosting path, affected files, `<selector-id>.preference-selector.contract.json` path,
  validator command, Zapp configuration procedure, and device test plan.

Wait for explicit approval. Refresh the contract if a material decision changes.

## 4. Implement The Contract

1. Build the feed through the target project's established static, Pipes/DSP, or endpoint
   surface. Do not introduce a service solely to host a selector.
2. Emit stable tags independent of translated labels. Match `behavior.select_mode` and
   `behavior.current_selection` to the approved state contract.
3. Prefer `preference_editor` or `push_topic` when one role completes the behavior. For a
   composite flow, emit the approved `tap_actions.actions` sequence. Place a confirmation dialog
   before consequential effects. A UI-language change uses `setUILanguage` followed by
   `appRestart`.
4. For remote actions, configure only the project artifacts needed for the approved Zapp
   Endpoint/CloudEvent. Keep credentials out of feeds and logs; use HTTPS and the approved
   context mechanism.
5. Create one versioned contract file per deployable selector and validate it with the feed.
   Start from [the templates](templates/README.md) only after the decisions are resolved.
6. Add or update `zapp-preference-selector-configuration.md` beside the target README by
   default for deployable work. Link it from the README when possible. The developer may
   decline it; skip it for explicitly throwaway/mock-only work.

Completion: the feed and supporting project artifacts realize the approved contract.

## 5. Verify And Hand Off

1. Run the target project's focused tests and typecheck/formatter while implementing, then its
   full suite before completion.
2. Run the skill-local validator against the emitted feed and its contract file. For dynamic
   feeds, validate representative default, selected, and stale-value contexts. Run a safe
   remote probe only when its endpoint and credentials are available.
3. Verify on devices: initial hydration, selected state, selection changes, relaunch
   persistence where applicable, re-entry, default fallback, downstream update, and every
   platform or approved divergent path.
4. Include `## Zapp Configuration` in the final handoff: feed URL, screen/component binding,
   selected cell style, Endpoint/context setup, refresh or restart configuration, entry/re-entry
   flow, and device validation steps. Give values to the developer; do not mutate Zapp Studio.
5. Report the approved contract, files changed, validation command/result, project checks,
   device result or exact blocker, required configuration/secrets, platform deviations, and
   remaining deployment prerequisites. Server analytics appear only if requested.

Completion: contract validation passes, device verification passes or is explicitly blocked,
and the developer has the exact Zapp configuration values to apply.
