Agent SkillsUsefulSoftwareCo/executor › wrdn-effect-promise-exit

wrdn-effect-promise-exit

GitHub

将React中基于promise模式的effect-atom变异处理从try/catch重构为promiseExit与显式Exit处理,以符合Effect错误模型并避免乐观更新依赖异常。

.agents/skills/wrdn-effect-promise-exit/SKILL.md UsefulSoftwareCo/executor

Trigger Scenarios

lint或review提示mutation调用周围存在try/catch 需要修复UI处理器中的错误/忙碌状态设置逻辑

Install

npx skills add UsefulSoftwareCo/executor --skill wrdn-effect-promise-exit -g -y
More Options

Non-standard path

npx skills add https://github.com/UsefulSoftwareCo/executor/tree/main/.agents/skills/wrdn-effect-promise-exit -g -y

Use without installing

npx skills use UsefulSoftwareCo/executor@wrdn-effect-promise-exit

指定 Agent (Claude Code)

npx skills add UsefulSoftwareCo/executor --skill wrdn-effect-promise-exit -a claude-code -g -y

安装 repo 全部 skill

npx skills add UsefulSoftwareCo/executor --all -g -y

预览 repo 内 skill

npx skills add UsefulSoftwareCo/executor --list

SKILL.md

Frontmatter
{
    "name": "wrdn-effect-promise-exit",
    "description": "Replace React\/effect-atom mutation handlers that use promise-mode plus try\/catch with promiseExit and explicit Exit handling. Use when lint or review flags try\/catch around useAtomSet mutation calls, especially UI handlers that set error\/busy state after a failed mutation.",
    "allowed-tools": "Read Grep Glob Bash"
}

You fix one pattern: a React handler awaits an effect-atom mutation in mode: "promise" and catches failures with try/catch.

The preferred UI boundary is mode: "promiseExit" plus Exit.isFailure. This keeps mutation failures as values, matches Effect's error model, and prevents optimistic mutation cleanup from depending on thrown exceptions.

Trace before changing

  1. Find the mutation setter. Look for const doX = useAtomSet(<mutationAtom>, { mode: "promise" }).
  2. Confirm it is an effect-atom mutation boundary. The setter should come from @effect/atom-react and a mutation atom from ./atoms, ../api/atoms, or plugin React atoms.
  3. Find thrown-control handling. The same handler has try { await doX(...) } catch (e) { ... }, usually setting error text, resetting adding/saving, or showing a toast.
  4. Check for non-mutation async work in the same block. If the block also awaits follow-up mutations, convert those to promiseExit too or keep a narrow boundary only around truly non-effect APIs.
  5. Do not rewrite unrelated local async code. Probe requests, OAuth popup helpers, fetch, and browser APIs may need a different skill unless the lint finding specifically points at the mutation call.

Fix shape

  • Change the setter to { mode: "promiseExit" }.
  • Import * as Exit from "effect/Exit" if missing.
  • Import * as Option from "effect/Option" only when extracting an optional error.
  • Replace try/catch around the mutation with:
    • const exit = await doX(args);
    • if (Exit.isFailure(exit)) { ...; return; }
    • success work after the failure branch.
  • Use Exit.findErrorOption(exit) when preserving an existing error message or typed error branch.
  • Keep existing typed error handling when present, e.g. SecretInUseError, ConnectionInUseError.

Bad

const doAdd = useAtomSet(addGraphqlSource, { mode: "promise" });

const handleAdd = async () => {
  setAdding(true);
  setAddError(null);
  try {
    await doAdd({
      params: { scopeId },
      payload,
      reactivityKeys: sourceWriteKeys,
    });
    props.onComplete();
  } catch (e) {
    setAddError(e instanceof Error ? e.message : "Failed to add source");
    setAdding(false);
  }
};

Good

import * as Exit from "effect/Exit";
import * as Option from "effect/Option";

const doAdd = useAtomSet(addGraphqlSource, { mode: "promiseExit" });

const handleAdd = async () => {
  setAdding(true);
  setAddError(null);
  const exit = await doAdd({
    params: { scopeId },
    payload,
    reactivityKeys: sourceWriteKeys,
  });
  if (Exit.isFailure(exit)) {
    const error = Exit.findErrorOption(exit);
    setAddError(
      Option.isSome(error) && error.value instanceof Error
        ? error.value.message
        : "Failed to add source",
    );
    setAdding(false);
    return;
  }
  props.onComplete();
};

Follow-up mutation chains

If success work depends on the mutation result, read it after the failure branch:

const exit = await doAdd(args);
if (Exit.isFailure(exit)) {
  setAdding(false);
  return;
}

const sourceId = exit.value.namespace;

If a follow-up effect-atom mutation can fail and the UI treats that as add failure, make that setter promiseExit too and branch the same way. Do not put the follow-up mutation in try/catch just because the first mutation now returns Exit.

What not to report

  • try/catch around non-effect APIs such as new URL, JSON.parse, raw fetch, or browser popup code. Those may be real lint findings, but they need a different remediation skill.
  • useAtomSet(..., { mode: "promise" }) with no local failure handling and no lint finding. Some call sites intentionally let callers decide the boundary.
  • Tests or SDK/server Effect code. This skill is for React/effect-atom UI mutation handlers.
  • Manual optimistic placeholder cleanup. Use wrdn-effect-atom-optimistic for that; if both patterns appear together, fix optimistic plumbing first, then use promiseExit for the remaining mutation boundary.

Output requirements

When reviewing, report:

  • File and line of the useAtomSet(..., { mode: "promise" }) or try/catch.
  • Mutation being called.
  • Why it should return Exit at this UI boundary.
  • Fix: the exact setter mode and the failure branch to add.

When editing, keep changes local to the handler and imports unless a follow-up mutation in the same success path must also become promiseExit.

Version History

  • fd4fb02 Current 2026-07-05 10:55

Same Skill Collection

.agents/skills/stack/SKILL.md
.agents/skills/wrdn-effect-atom-optimistic/SKILL.md
.agents/skills/wrdn-effect-atom-reactivity-keys/SKILL.md
.agents/skills/wrdn-effect-raw-fetch-boundary/SKILL.md
.agents/skills/wrdn-effect-schema-boundaries/SKILL.md
.agents/skills/wrdn-effect-schema-inferred-types/SKILL.md
.agents/skills/wrdn-effect-typed-errors/SKILL.md
.agents/skills/wrdn-effect-value-inferred-types/SKILL.md
.agents/skills/wrdn-effect-vitest-tests/SKILL.md
.agents/skills/wrdn-package-boundaries/SKILL.md
.agents/skills/wrdn-typescript-type-safety/SKILL.md
.claude/skills/emulate/SKILL.md
.claude/skills/prod-telemetry/SKILL.md
.claude/skills/self-contained-modals/SKILL.md
.skills/cli-release/SKILL.md
.skills/effect-atom-optimistic-updates/SKILL.md
.skills/effect-http-testing/SKILL.md
.skills/effect-use-pattern/SKILL.md
.skills/graphite/SKILL.md
.skills/warden-security-review/SKILL.md

Metadata

Files
0
Version
837e404
Hash
906ed280
Indexed
2026-07-05 10:55

Home - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-03 04:52
浙ICP备14020137号-1 $Map of visitor$