実際の製品を操作して、利用者が確認できる動作証拠を集め、検証計画に沿った受け入れレポートとして公開するスキルです。
- 変更後の製品動作を実地で検証したいとき
- 画面キャプチャなどの証拠を集めたいとき
- 検証計画とレポートを作成したいとき
Zustandのストア設計や型、セレクター、楽観的更新を整理し、local-replicaを使う一覧・詳細データと従来型ストアの扱い方を案内します。
Use for Zustand stores: state shapes and type sources, state-only stores with xActions classes, replica-backed list/detail data (local-replica), selectors, optimistic writes, and legacy slice/internal_* action composition.
実行スコア 未検証
インストール方法を見るZustandストアの状態、型、読み取り方法、アクションの配置を整理するガイドです。新しいストアでは状態とアクションを分け、コンポーネントはセレクターで状態を読み、専用クラスのアクションを呼び出す構成を案内します。サーバー由来の一覧・詳細データには local-replica を使い、ローカル保存からの復元、再検証、ページング、楽観的更新と失敗時のロールバックを扱います。従来のsliceや internal_* アクションを持つストアについては、既存形式を編集するときの参照先も示します。
ストアを新設・移行するとき、一覧と詳細の型やキャッシュ方法を決めるとき、サーバーデータの同期処理を実装するときに役立ちます。既存のレガシーストアを変更する際に、現行方式との境界を確認する用途にも向いています。
特記事項はありません。
この紹介文は、公開されている SKILL.md をもとに AI(OpenAI Codex)が作成しました。正確な仕様は下の原文を確認してください。
SKILL.md の記述から、注意が要る操作と導入の前提を AI が確認しました。点数は実際に動かした結果(実行検証)だけで付けています。
点数には入れていません。 2026年10月26日 時点で AI(OpenAI Codex)が判定しました。目安なので、入れる前に原文も確認してください。
インストールする前に、エージェントに与えられる指示の中身を確認できます。
@lobechat/types, not @lobechat/database.xxxDetailMap: Record<string, Detail>); never hold a single currentDetail object.xxxSelectors aggregates (selectors.ts), not ad-hoc lambdas repeated across components.Actions stay out of the Zustand state. Reference: src/store/page.
| File | Owns |
|---|---|
store.ts | useXStore = createWithEqualityFn<XState>()(devtools(() => initialState), shallow): state only, no methods |
privateAction.ts | XPrivateAction: replica slices, entity links, and write helpers shared by public actions. Not exported from index.ts |
action.ts | XActionImpl (the public API) and the singleton xActions = new XActionImpl(setState, getState, new XPrivateAction(…)) |
useXStore(selector) and call xActions.foo() directly. Never select an action out of the store.xActions.useFetchX(params).this.foo(). Private helpers are reached through this.#private. Do not add internal_* methods to the store to share logic between classes.this.#set(partial, false, n('actionName')) with const n = setNamespace('x').reset() on the public class and register xActions in resetableActions in src/store/utils/userDataStores.ts.xActions and assert on useXStore.getState(). To mock in component tests: vi.mock('@/store/x', () => ({ xActions: { foo: vi.fn() }, useXStore: … })).Server lists and details the UI paints go through @/libs/replica, not a hand-written SWR onSuccess + reducer. The engine owns hydration from IndexedDB, head revalidation, paging, optimistic overlays with rollback, and scope (user + workspace) isolation. API reference: the local-replica README. The engine is maintained in lobehub/local-replica: fix it there, publish, then bump the dependency here.
defineReplica / definePagedReplica) in the store's projection.ts, converting server rows at the boundary.xxxMap: Record<key, TData>) and its bookkeeping (xxxReplica: createReplicaState()).createReplicaSlice(resource, { get, set, stateKey: 'xxxReplica', view: recordLens('xxxMap'), … }). When the same entity lives in several replicas (list row + detail), link them with linkReplicaEntity([list, detail]).slice.useSync(params) returns only fetch flags (isHydrated, isValidating, error, revalidate). Data comes from selectors over xxxMap. "Entry is undefined" is the loading signal — do not add xxxInit flags or loadingXxxIds.await slice.fetch(params) ({ fresh: true } after a write). Never call the service and slice.replace(...) by hand, because that skips the scope, removal, clear and superseded-request guards. Side effects of every response (not-found maps, seeding another store) go in the slice effects (onApplied / onMissing / onPurge / onError) with isMissing, not in one hook's onSuccess.useSync hydrates only after the component mounts. For a list that must paint from the local copy, add a preHydrate action (ensureScope + hydrate) and call it from the route's loader through a lazy wrapper (src/spa/router/pageListLoader.ts, agentChatTopicListLoader.ts) bounded by settleWithin(…, PRE_PAINT_HYDRATE_TIMEOUT) from @/libs/replica/prePaint. @/libs/replica presets the cache scope, IndexedDB / localStorage storage (AppIndexedDBStorage / AppLocalStorage in @/libs/replica/storage) and the app's SWR driver; the package README stays app-agnostic.slice.optimistic(key, apply, serverCall) or entity.optimistic(id, fn | 'remove', serverCall). A failed call rolls back to the confirmed value, so deletes are optimistic too. Rows that exist only on the client (temp ids) are declared with isClientOnly and seeded with update(key, fn, { persist: false }).Outside test seeding, write a replica's view only through its slice. A plain set bypasses the engine's bookkeeping (persistence, rollback base, entity links).
Stores that still flatten action classes into state (flattenActions, create*Slice, internal_*, internal_dispatch* + reducers, SWR onSuccess syncing) follow Legacy slices. Use that layout only when editing one of those stores; migrate to the layouts above when moving its data onto a replica.
まだレビューはありません。使ってみた感想をお寄せください。
ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。
まだコメントはありません。最初のコメントを書いてみませんか。
実際の製品を操作して、利用者が確認できる動作証拠を集め、検証計画に沿った受け入れレポートとして公開するスキルです。
LobeHubにAIモデルプロバイダーを追加し、実行時連携からモデル表示、設定、ブランド表記、文書化、動作確認まで進めるスキルです。
ユーザー設定の初期値をサーバー側の環境変数で切り替えるため、型定義や設定の組み立て、ユーザーストアへの反映、環境変数の例と説明書きを追加する手順です。
エージェント実行中の各段階をフックで監視し、ツール呼び出しの模擬・制御や人の承認、圧縮、サブエージェント処理に介入する仕組みを扱います。
イベントを起点にエージェントのバックグラウンド処理を組み立て、ソース・シグナル・アクション・ポリシーの役割分担や非同期連携を実装するためのスキルです。
DiscordやSlackなどの実際のチャットアプリでボットにメッセージを送り、応答を画面で確認する受け入れテストを行うスキルです。