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.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add lukas-grigis/ralphctl --skill ralphctl-abstraction-first --agent claude-codeInstalls 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 automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/lukas-grigis-ralphctl-abstraction-first)More formats (shields.io, HTML) on the badges page.
---
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.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!