From amplify
Transforms SPEC.md, PRD, RFC, ADR into narrative STORY.md retellings preserving all technical details while making them engaging. Use for 'spec story' or 'narrative version' requests.
npx claudepluginhub wunki/amplify --plugin ask-questions-if-underspecifiedThis skill uses the workspace's default tool permissions.
Turn a dense SPEC.md into something you'd actually read on purpose.
Creates or updates SPEC.md documents from requirements, notes, or interview output, structuring into sections for goals, design, edge cases, security, testing, and success criteria. Use for feature specs.
Provides conventions for writing self-contained, implementation-ready spec documents. Distinguishes specs from docs; covers structure including data model, architecture, security, operations, scope, and deliverables.
Generates technical specs with implementation-ready stories. Activates automatically when users mention 'quick spec' or 'tech spec'.
Share bugs, ideas, or general feedback.
Turn a dense SPEC.md into something you'd actually read on purpose.
A retelling of a technical spec that has a pulse. Same information, completely different experience. The spec is the blueprint. This is the version that makes you want to go build the thing.
Think less "requirements document" and more "the best Slack message your tech lead ever wrote."
If the user points to a specific file, use that.
Otherwise, search for a spec file in this order:
SPEC.md in the project root.md file in the specs/ or docs/ directory whose name suggests it is a spec, PRD, RFC, or ADRIf no spec file exists anywhere, tell the user and stop. Do not suggest other skills.
Read every section. Understand the full picture before writing a word. Look for:
Note any sections already written in narrative prose — absorb their voice but rewrite them to fit the unified story. Do not paste them in verbatim.
Default to first person plural ("we") — it creates a sense of shared ownership and is the most natural voice for engineering narratives. Use second person ("you") only if the spec itself is framed as a user-facing tutorial or if the dominant concern is the developer's experience of building the feature. Pick one voice and hold it throughout.
The reader is the person about to build this thing. They're smart, they're busy, and they'll bail if you bore them.
Structure the narrative as a story with tension and payoff:
The hook (1-2 paragraphs): Open with the problem, not the solution. Make the reader feel the pain before you reveal the fix. If the problem is boring, find the angle that isn't. Every feature exists because something was bad enough that someone decided to spend money fixing it. Find that nerve.
The lay of the land (1-3 paragraphs): What exists today. What's broken, missing, or held together with duct tape. If there were previous attempts, they make great material: "We tried X in 2024. It worked until it didn't."
The plan (the bulk): Walk through the design like you're explaining it to a colleague who's following along. Don't enumerate components; introduce them as they become relevant. "When a user hits submit, the first thing that happens is..." pulls the reader through. "The system consists of three microservices" puts them to sleep.
The hard parts (1-3 paragraphs): This is where the story gets good. Edge cases, race conditions, the thing that will definitely bite someone at 2am. Lean into it. These aren't risks to be mitigated; they're the plot twists.
The unknowns (1 paragraph): What's still fuzzy. Frame it with honesty: "We don't know yet" is more interesting than "TBD".
The finish line (1 paragraph): What "done" looks like, in words a human would say.
This is the whole point. Readable is table stakes. Entertaining is the goal.
Build tension. Set up the problem before the solution. "The obvious approach is X. Here's why it falls apart." The reader should feel the constraint before they see the escape route.
Have reactions. When something in the spec is clever, say so. When something is gnarly, admit it. "This part is elegant" and "this part is a nightmare" are both more engaging than neutral description. Your genuine response to the material is what makes it human.
Use surprise. Lead the reader one direction, then pivot. "You'd think we could just cache it. You'd be wrong." Unexpected turns keep people reading.
Be specific and visceral. "The database melts" is better than "performance degrades." "The user stares at a spinner for eleven seconds" is better than "latency increases." Concrete details create mental images. Mental images create engagement.
Vary your rhythm. Long sentence that builds and layers and adds context. Short one that lands. Fragment for emphasis. Then back to flowing prose that carries the reader forward. Monotonous sentence length is the silent killer of interesting writing.
Use callbacks. Reference something from earlier in an unexpected way. "Remember that race condition we mentioned? It gets worse." This rewards the reader for paying attention and gives the piece structural cohesion.
Earn your digressions. Brief asides that add color are great. Parenthetical observations, one-sentence opinions, the occasional "yes, really." But every aside must either clarify, entertain, or both. If it does neither, cut it.
Name the absurdity. Software is full of absurd constraints. When something is ridiculous, say it. "We need four database tables for what is essentially a to-do list" is funny because it's true, and the reader was thinking it anyway.
Do:
Don't:
Use a handful of headings to create breathing room. Make them interesting enough that someone scanning would stop and read.
Good headings:
Bad headings:
SPEC.md, write to STORY.md in the same directory.-story before the extension: specs/feature.md → specs/feature-story.md, docs/RFC-42.md → docs/RFC-42-story.md.Aim for roughly 40-60% of the spec's word count. Dense specs get compressed; thin specs might expand where context helps. Floor: never produce fewer than 300 words regardless of source length — a stub is not a story. The narrative should feel like a satisfying read, not a marathon. If it's boring at any point, it's too long at that point.
Before finishing:
Spec:
## Edge Cases & Error Handling
- If the webhook delivery fails after 3 retries, mark the event as `failed`
and emit a `webhook.delivery_failed` metric
- If the target URL returns a redirect, do not follow it; treat as a failure
- If the payload exceeds 256KB, reject at ingestion with a 413 response
- Race condition: two events for the same resource arriving within the retry
window should be deduplicated by event_id
Story:
## The part where deliveries go wrong
Most webhook deliveries are boring in the best way. Fire, receive, done. But
the interesting ones are the failures.
We give each delivery three chances. If it still can't land after three retries,
we mark it `failed` and fire a `webhook.delivery_failed` metric. At that point,
it's on the consumer's side and our monitoring picks it up.
One policy worth calling out: we don't follow redirects. If someone's endpoint
starts bouncing us to a different URL, we treat that as a failure. It might seem
strict, but the alternative is chasing redirect chains into the void, which is
both a security risk and a debugging nightmare.
Payloads over 256KB get rejected at the door with a 413. No negotiation. This
keeps the queue healthy and gives callers a clear signal to break up their data
instead of trying to shove a novel through the pipe.
Now for the genuinely tricky bit: two events for the same resource can arrive
within the retry window. Without deduplication, you get double-processing during
transient failures, which is the kind of bug that works perfectly in staging and
ruins someone's Tuesday in production. We deduplicate by `event_id`, so the
second arrival is a no-op. Simple fix, catastrophic without it.
Spec:
### Data Model
| Table | Fields | Notes |
|-------|--------|-------|
| events | id, type, payload, status, created_at | status enum: pending, delivered, failed |
| deliveries | id, event_id, attempt, status_code, responded_at | One row per attempt |
| subscriptions | id, url, secret, active, created_at | HMAC secret for signature verification |
Story:
The data model is three tables, which feels right for this level of complexity.
`events` is the source of truth: every incoming webhook gets a row with its
payload and a status that moves from `pending` to `delivered` or `failed`. Think
of it as the manifest.
`deliveries` tracks each attempt separately. One event might generate three
delivery rows if the first two fail. This is what makes retry debugging possible
instead of maddening, you can see exactly which attempt got a 503 and which
finally landed.
`subscriptions` is where consumers register their endpoint URL and receive an
HMAC secret. Every outgoing delivery is signed with this secret, so consumers
can verify it's actually us knocking and not some random POST from the internet.