effect-deslopify-idiomatic
Effect Deslopify (Idiomatic Remediation)
Systematic audit and remediation of Effect-TS code to library-grade idiomatic standards.
Companion skills (install separately): effectts (pattern reference), sdd (methodology). These provide the pattern reference and methodology this skill orchestrates.
Target
Apply to any Effect-TS codebase, package, or file path.
Mission
- De-slopify the target
- Make code library-grade idiomatic Effect
- Keep behavior stable unless fixing a confirmed bug
Workflow
1. Audit (SDD Phases 1-4)
Run SDD audit mode across phases 1-4 on the target.
2. Gap Analysis
Produce a gap list covering:
- Schema modeling (bare brands, missing constraints, manual mappers)
- Service boundaries (wrong abstraction level, god services)
- Error channels (silent swallowing, wrong error types)
- Layer wiring (missing deps, provide vs provideMerge)
- Purity violations (impure ops outside Effect tracking)
- Exhaustiveness (switch instead of Match.exhaustive)
- Test coverage (missing property tests, bun scripts)
3. Decide: Remediate or Rewrite
For each gap:
- Remediate if architecture is sound and gaps are localized
- Rewrite only if architecture is unsalvageable (majority of phases FAIL)
4. Implement Fixes
Implement highest-impact fixes. Priority order:
- Bugs (incorrect behavior, discarded Effect values)
- Schema constraints (bare brands, missing validation)
- Error modeling (Data.TaggedError -> Schema.TaggedError)
- Service patterns (Effect.fn, annotateLogs)
- Test gaps (property tests, vitest conversion)
5. Regression Tests
Add/keep regression tests for bug fixes (TDD: failing test first, then fix).
6. Verify Gates
Run all applicable gates:
- Your project's typecheck command (e.g.
npx tsc --noEmitorpnpm check) npx effect-language-service quickfixes --project tsconfig.json(if configured)- Relevant test suites
Idiomatic Constraints
These are non-negotiable for library-grade Effect code:
| Constraint | Why |
|---|---|
No as any |
Type escapes hide real errors |
No silent catchAll error swallowing |
Errors must be logged or propagated |
No raw fetch when typed client exists |
Duplicating URLs loses type safety |
| No ad-hoc mutable state in Effect paths | Use Ref for tracked state |
Impure ops wrapped in Effect.sync / Effect APIs |
Effect must track all side effects |
Match.exhaustive not switch |
Compile-time case coverage |
| Errors modeled explicitly | Schema.TaggedError with typed channels |
Effect.fn on all service methods |
Automatic tracing spans |
Effect.annotateLogs per service module |
Structured observability |
yield* new TaggedError() in generators |
Not Effect.fail(new TaggedError()) |
Before / After Examples
Bare Brand -> Constrained Brand
// BEFORE (sloppy): accepts empty strings, whitespace, anything
const UserId = Schema.String.pipe(Schema.brand("UserId"))
// AFTER (idiomatic): enforces domain invariants
const UserId = Schema.NonEmptyString.pipe(
Schema.pattern(/^usr_[a-z0-9]+$/),
Schema.brand("UserId")
)
Manual Tracing -> Effect.fn
// BEFORE (sloppy): manual withSpan, no argument capture
findById: (id: UserId) =>
sql`SELECT * FROM users WHERE id = ${id}`.pipe(
Effect.flatMap(rows => decode(rows[0])),
Effect.withSpan("UserRepo.findById"),
),
// AFTER (idiomatic): Effect.fn captures args + creates span
findById: Effect.fn("UserRepo.findById")(function*(id: UserId) {
const rows = yield* sql`SELECT * FROM users WHERE id = ${id}`
if (rows.length === 0) return yield* new UserNotFound({ userId: id })
return yield* Schema.decodeUnknown(User)(rows[0])
}),
Silent Error Swallowing -> Explicit Handling
// BEFORE (sloppy): error silently disappears
const result = yield* dangerousOp.pipe(
Effect.catchAll(() => Effect.succeed(fallback))
)
// AFTER (idiomatic): error logged before fallback
const result = yield* dangerousOp.pipe(
Effect.tapError((e) => Effect.logWarning("Falling back", { error: e })),
Effect.catchAll(() => Effect.succeed(fallback))
)
Output
After running deslopify, report:
- Changed files (with summary of what changed)
- Anti-patterns removed (count by category)
- Test/gate results (pass/fail)
- Residual risks + follow-ups (anything not fixed in this pass)
More from artimath/effect-skills
effectts
Idiomatic Effect-TS patterns for TypeScript functional programming. USE THIS SKILL WHEN: Writing new Effect services or layers, debugging Effect type errors (layer composition, error types), choosing between Effect patterns, setting up Effect testing. TRIGGERS ON: 'effect pattern', 'Layer.provide', 'Context.Tag', 'effect service', 'effect error', 'effect test', 'idiomatic effect'. NOT FOR: general TypeScript without Effect.
19sdd
Service-Driven Development workflow for Effect-TS. Schema-first, type-driven, property-tested. USE THIS SKILL WHEN: Designing a new feature spanning 3+ services, sketching service boundaries before implementation, user says 'design', 'sketch', 'SDD', 'service-driven', planning multi-service composition. NOT FOR: single-service CRUD, implementing against an existing spec. TRIGGERS ON: 'design services', 'sketch services', 'SDD', 'service-driven', 'type-driven design', 'design the API first', 'audit services', 'bring to SDD standard', 'SDD audit'
11effect-deep-audit
Deep audit of an Effect-TS codebase against actual Effect core team patterns. Produces a tiered finding list + executable DAG plan, then systematically rewrites non-idiomatic code. USE THIS SKILL WHEN: 'audit this effect code', 'is this idiomatic effect', 'deep audit', starting a new Effect project and want to verify patterns, refactoring an Effect codebase toward library-grade quality, reviewing code before it ships to production. NOT FOR: Greenfield Effect projects (use effectts skill).
11