Cross-phase skill — design the shape of the change (entities, boundaries, seams) before generating code, tasks, or acceptance criteria. Failure mode is "big blob" output that obscures the core change.
Installs into .claude/skills of the current project.
Are you the author of Ralphctl Abstraction First?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/lukas-grigis-ralphctl-abstraction-first)
---
name: ralphctl-abstraction-first
description: Cross-phase skill — design the shape of the change (entities, boundaries, seams) before generating code, tasks, or acceptance criteria. Failure mode is "big blob" output that obscures the core change.
---
# Abstraction-First
> Concept
>
> from [SPDD (Zhang & Xia, martinfowler.com) — "Abstraction-First"](https://martinfowler.com/articles/structured-prompt-driven/abstraction-first.html).
> Adapted for ralphctl's three phases.
The shape of the change comes before the words that describe it. Name the entities, the boundaries, and the
seams the change touches **first**; the criteria, tasks, or code that follow are then arguments about that
shape, not freeform prose. Skip this and the output reads as a "big blob" — duplicated logic, blurred
responsibilities, work that has to be reviewed wholesale rather than incrementally.
## When this applies
- **Refine** — name the entities and the boundary of the change before listing acceptance criteria. "Adds a
`UserBilling` aggregate that exposes `cancelSubscription`" is the right altitude. "The cancel button must
turn red" is too specific to be the spec.
- **Plan** — sketch which existing components the change extends, which new ones it introduces, and the seams
between them, before splitting into tasks. The task list is then the decomposition of a known shape, not a
guess about one.
- **Execute** — re-read the task's verification criteria and the surrounding code's existing pattern before
opening an editor. The "abstraction" at this altitude is the contract the task already declared; matching it
is the job.
## What to do
1. **Name the entities.** Real-world nouns the change talks about — domain objects, aggregates, modules,
external systems. If you cannot name three of them, the change is either trivial or under-specified.
2. **Draw the boundary.** Which files / directories / packages are in scope? Which are explicitly out? An
ambiguous boundary is the same problem as an ambiguous criterion — it lets later work drift.
3. **Identify the seam.** Where does the new behaviour meet the existing system? An interface, a port, a
route, a CLI command, a database table. The seam is where regressions hide; call it out by name.
4. **Only then describe behaviour.** Acceptance criteria, task steps, code — all of these are downstream of
the shape. Writing them first is what produces the "big blob".
## Anti-patterns
- **Specifying behaviour before naming entities** — produces criteria that read as a wishlist rather than a
spec. Reviewers cannot tell what the change actually _is_.
- **Listing files instead of naming a boundary** — "touches `foo.ts`, `bar.ts`, `baz.ts`" is not a boundary;
it is a side effect of one. Name the module or aggregate they belong to.
- **Inventing an abstraction the codebase does not have** — if the existing code has no `UserBilling`
aggregate, do not name one in the spec unless creating it is part of the change.