change-proposal
$
npx mdskill add EpicenterHQ/epicenter/change-proposalVisually propose code changes before implementation
- Solves the problem of unclear or risky code changes
- Uses before/after diffs, diagrams, and dependency graphs
- Analyzes code context and user intent to generate options
- Delivers visual comparisons and reasoning to the user
SKILL.md
.github/skills/change-proposalView on GitHub ↗
---
name: change-proposal
description: 'Present proposed code changes visually before implementing. Use when: "show me options", "compare approaches", "what should we do", or when changes need before/after comparison.'
---
# Change Proposal
When proposing non-trivial changes, make your reasoning visible before acting. The user should see what will change, why, and what alternatives were considered:before a single file is edited.
Follow [writing-voice](../writing-voice/SKILL.md) for prose sections.
## When to Use This
- Multiple valid approaches exist (show competing options)
- Changes span 3+ files (show the dependency graph)
- Architecture or ownership shifts (show before/after diagrams)
- Lifecycle or data flow changes (show the flow)
- The user asks "what do you think?" or "how should we do this?"
For trivial changes (typo fix, single-line edit, obvious bug), skip this and just do it.
If the change reshapes a product surface (new command, new route, new primary API), state the post-change one-sentence meaning using [one-sentence-test](../one-sentence-test/SKILL.md) alongside the diagrams and diffs. It anchors the proposal to what the product *is*, not just what changed.
## The Three Tools
### 1. Before/After Diffs
Show what specific code will change. Use fenced diff blocks with file paths.
````diff
--- a/workspace.ts
+++ b/workspace.svelte.ts
@@ createWorkspaceState()
- let client = buildWorkspaceClient();
+ let client = $state(buildWorkspaceClient());
return {
get current() { return client; },
- async reset() {
- await client.wipe();
- client = buildWorkspaceClient();
+ async reset(options?: { key?: Uint8Array }) {
+ await client.dispose();
+ client = buildWorkspaceClient(options);
},
};
````
Rules:
- Show the smallest meaningful diff, not the whole file
- Include enough context lines (3-5) to understand placement
- Group related changes together, separate unrelated ones
- Label each diff with the file path and function/scope
### 2. ASCII Architecture Diagrams
Show how components relate before and after the change. Use the characters from [progress-summary](../progress-summary/SKILL.md): `┌ ┐ └ ┘ ─ │ ├ ┤ ┬ ┴ ┼ ▼ ▲ ──→ ←──`
**Before:**
```
auth ──signOut()──→ workspace.reset() ──→ internally rebuilds
│ (self-manages lifecycle)
├── dispose()
├── wipe()
└── client = build()
```
**After:**
```
auth ──signOut()──→ workspace.current.dispose()
setWorkspaceClient(build())
│
workspace is a reactive slot ← auth owns lifecycle
```
When to use which diagram type:
- **Ownership diagrams**: Who controls what (arrows show control flow)
- **Layer diagrams**: Stacked boxes for architectural layers
- **Flow diagrams**: Data or control moving between components
- **Journey diagrams**: Evolution from attempt A → B → C
### 3. Comparison Tables
When multiple approaches exist, present them as a table with clear trade-off dimensions.
```
A: Self-managed B: Slot + builder C: Auth owns state
─────────────── ───────────────── ──────────────────
Who holds $state? workspace workspace auth
Who decides wipe? workspace auth (explicit) auth (explicit)
Circular deps? same as today same as today WORSE
God module risk? workspace neither auth
```
Rules:
- Rows are dimensions the user cares about
- Columns are approaches
- Use short phrases, not sentences
- State your recommendation after the table, not inside it
## Proposal Structure
For non-trivial changes, present in this order:
1. **One sentence**: What you're proposing and why
2. **Diagram**: Architecture before/after (or competing approaches side-by-side)
3. **Diffs**: Concrete code changes for the recommended approach (hardest file first)
4. **Trade-offs**: What you gain, what you lose, what stays the same
5. **Ask**: "Should I proceed with [recommendation], or prefer [alternative]?"
## Scaling by Complexity
| Change scope | What to show |
| --- | --- |
| 1 file | Just the diff, no diagram |
| 2-5 files | Diff of the hardest file + one diagram showing relationships |
| 5+ files | Full proposal: comparison table, diagrams, diffs for hardest 2-3 files |
| Architecture decision | Comparison table mandatory, even if only 2 options |
| Competing approaches | All three tools: diagram per approach, diff per approach, comparison table |
## Good vs Bad Proposals
### Good
> `workspace.ts` currently self-manages its lifecycle. I'd split it: workspace becomes a reactive slot + builder, auth owns the lifecycle decisions.
>
> ```
> writes reads
> auth ──────────────────► workspace.svelte.ts ◄──── consumers
> builds, sets let client = $state() .current
> decides wipe set(newClient) via $effect
> ```
>
> ```diff
> --- a/workspace.ts (createWorkspaceState)
> +++ b/workspace.svelte.ts
> - let client = buildWorkspaceClient();
> + let client = $state(buildWorkspaceClient());
> ```
>
> Trade-off: auth gains 10 lines of explicit lifecycle code, workspace loses its god-object methods. Net simpler because lifecycle decisions are visible at the call site.
>
> Should I proceed with this, or keep workspace self-managed?
### Bad
> I'll refactor workspace.ts to use a slot pattern and move lifecycle management to auth.svelte.ts. This involves changing how the client is created and disposed, updating the state management to use $state, and modifying the reset function to accept an optional key parameter. The consumers will use $effect to automatically rebind when the workspace changes.
The bad version describes changes in prose. The good version shows them.
## What to Avoid
- **Prose-only proposals**: If you can draw it, draw it. If you can diff it, diff it.
- **Showing every file**: Show the hardest 2-3. Mention the rest as "same pattern."
- **Burying the recommendation**: Lead with your pick, then show alternatives.
- **Fake precision**: Don't show a diff for code you haven't read yet. Read first, then diff.
More from EpicenterHQ/epicenter
- agent-goalWrite `/goal` prompts for long-running agent work in Codex or Claude Code. Use for slash goal, agent goal, durable objective, autonomous coding run.
- approachability-auditReview code as a new TypeScript developer. Use when code feels indirect, clever, hard to follow, or needs a pass on abstractions, names, first-read clarity.
- arktypeArktype: runtime validation, discriminated unions with .merge()/.or(), spread keys. Use when mentioning arktype, type(), union types, command/event schemas.
- attach-primitiveContract and invariants for `attach*` composition primitives in `packages/workspace` (side-effectful building blocks like attachIndexedDb, attachSqlite, attachBroadcastChannel, attachEncryption, attachTable, openCollaboration), and when to use `create*` (pure construction) instead. Use when writing or reviewing an `attach*` or `create*` function, naming a new workspace primitive, composing inside a workspace builder, or deciding whether a primitive registers listeners at call time.
- authEpicenter auth packages: `@epicenter/auth`, `@epicenter/auth-svelte`, OAuth sessions, identity state, auth-owned fetch/WebSocket, and workspace lifecycle binding. Use when editing Epicenter auth clients, session state, hosted sign-in, or auth/workspace integration.
- autumnAutumn billing in Epicenter: `autumn.config.ts`, `autumn-js` credit checks, `atmn` CLI, plan gates, and metered AI usage. Use when changing billing, pricing, credits, plan access, refunds, or usage events.
- better-auth-best-practicesBetter Auth server/client setup: `auth.ts`, generated schema, DB adapters, sessions, cookies, env vars, and plugins. Use when mentioning Better Auth, betterauth, auth handlers, OAuth, email/password, or session configuration.
- better-auth-security-best-practicesBetter Auth security hardening: rate limits, secrets, CSRF, trusted origins, cookies, sessions, OAuth tokens, and audit logging. Use when reviewing auth security, brute-force protection, token handling, or deployment safety.
- claude-code-consultUse this skill when the user asks to consult Claude, ask Claude Code, get another model's take, run a taste check, find cleaner options, or prepare a Claude prompt. Create a bounded second-opinion prompt or run a read-only Claude Code consult, then verify Claude's claims against local files.
- cloudflare-workersCloudflare Workers patterns for Worker runtime APIs, Durable Objects, KV, R2, D1, Queues, WebSockets, streaming responses, bindings, wrangler configuration, and deployment limits. Use when users mention Cloudflare Workers, Durable Objects, KV, R2, D1, Queues, wrangler, or edge runtime behavior.