@ericrisco/rsc 0.1.53 → 0.1.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.53",
2
+ "version": "0.1.54",
3
3
  "counts": {
4
4
  "skills": 258
5
5
  },
@@ -2549,7 +2549,7 @@
2549
2549
  },
2550
2550
  {
2551
2551
  "id": "lead-gen",
2552
- "description": "Use when you need to find and qualify prospects, build a target list, or score and prioritize leads before anyone reaches out — defining an ICP, sourcing named accounts/contacts from Apollo/ZoomInfo/Clay, deduping against the CRM, and ranking with a fit+intent+engagement model. Triggers: 'build me a prospect list', 'who should we sell to', 'score these leads', 'which accounts do we call first', 'tighten our ICP', 'is this cold list GDPR-safe', 'necesito una lista de clientes potenciales', 'califica estos leads', 'a qui truquem primer'. NOT writing or sending the outreach (that is cold-outreach), NOT tracking the deal after first contact (that is sales-pipeline).",
2552
+ "description": "Use when building and qualifying a prospect list before anyone reaches out — a falsifiable ICP, named accounts/contacts from Apollo/ZoomInfo/Clay, deduped against the CRM, tiered by fit+intent+engagement. NOT writing or sending the outreach (that is cold-outreach), NOT tracking the deal after first contact (that is sales-pipeline).",
2553
2553
  "tags": [
2554
2554
  "lead-generation",
2555
2555
  "prospecting",
@@ -2609,7 +2609,7 @@
2609
2609
  },
2610
2610
  {
2611
2611
  "id": "linkedin-carousels",
2612
- "description": "Use when designing a LinkedIn carousel / document post — the swipeable multi-page PDF that is currently the highest-reach native LinkedIn format — and you need the slide-by-slide build: a scroll-stopping cover hook, a narrative arc that pulls swipe-to-swipe, one focused idea per slide with real visual hierarchy, a payoff + CTA closer, and a PDF export spec. Triggers: 'turn this into a LinkedIn carousel', 'design a swipeable PDF document post', 'my carousel cover gets no swipes fix the hook', 'how many slides and what goes on each', 'restructure one-idea-per-slide', 'what size to export so it isnt cropped on mobile', 'convierte este post en un carrusel de LinkedIn', 'dissenya'm un carrusel de LinkedIn amb portada i CTA'. NOT the account/format plan (that is linkedin-strategy), NOT a text or single-image feed post (that is linkedin-content), NOT a spoken-to talk deck (that is presentations).",
2612
+ "description": "Use when building a LinkedIn carousel / document post — the swipeable multi-page PDF — slide by slide: cover hook, narrative arc, one idea per slide, CTA closer, PDF export spec. NOT the account/format plan (that is `linkedin-strategy`), NOT a text or single-image feed post (that is `linkedin-content`), NOT a 16:9 talk deck (that is `presentations`).",
2613
2613
  "tags": [
2614
2614
  "linkedin",
2615
2615
  "carousel",
@@ -2694,7 +2694,7 @@
2694
2694
  },
2695
2695
  {
2696
2696
  "id": "llm-pipeline",
2697
- "description": "Use when wiring several LLM calls into one production flow, when random 429s/timeouts/provider outages take a feature down, when adding a fallback model or a gateway in front of OpenAI/Claude, or when the bill explodes from uncached or flagship-everywhere calls. Triggers: 'chain these LLM calls', 'step 1 extracts step 2 summarizes', 'add a fallback if GPT fails use Claude', 'route easy requests to Haiku escalate to Opus', 'put a LiteLLM gateway in front', 'our bill tripled because we re-call the model on every request', 'semantic cache the responses', 'encadenar llamadas y cachear respuestas', 'cadena de crides a l'LLM amb fallback'. NOT prompt wording (that is prompt-engineering).",
2697
+ "description": "Use when wiring several LLM calls into a production flow: typed contracts between steps, a router/gateway so 429s, timeouts and outages fail over instead of taking you down, and cost control via caching, model tiers and abort caps. NOT single-prompt wording (that is `prompt-engineering`), NOT a model-driven tool loop (that is `building-agents`).",
2698
2698
  "tags": [
2699
2699
  "llm-orchestration",
2700
2700
  "llm-gateway",
@@ -2912,7 +2912,7 @@
2912
2912
  },
2913
2913
  {
2914
2914
  "id": "modal",
2915
- "description": "Use when running Python functions or GPU workloads serverlessly on Modal — defining a modal.App with inline container Images, scaling @app.function onto CPU/GPU, persisting weights or datasets in a Volume, scheduling jobs, serving an HTTP/ASGI endpoint, or choosing modal run vs serve vs deploy. Triggers: 'run my embedding job on an H100 without managing servers', 'cache HuggingFace weights across runs', 'my @app.function GPU string errors', 'gpu=modal.gpu.A100() fails', 'modal serve isn't hot-reloading my fastapi_endpoint', 'cold start too slow / keep a warm pool', 'ejecutar Python en GPU serverless', 'desplegar un model de difusió amb GPU sense servidor i exposar-lo per HTTP'. NOT managed prediction endpoints with no infra code (that is replicate) and NOT persistent SSH-able GPU pods rented by the hour (that is runpod).",
2915
+ "description": "Use when running Python or GPU workloads serverlessly on Modal — modal.App, inline container Images, gpu= on @app.function, Volumes for weight caching, Cron schedules, ASGI endpoints, modal run vs serve vs deploy. NOT managed prediction APIs with no container of your own (that is replicate); NOT SSH-able GPU boxes rented by the hour (that is runpod).",
2916
2916
  "tags": [
2917
2917
  "modal",
2918
2918
  "serverless",
@@ -3075,7 +3075,7 @@
3075
3075
  },
3076
3076
  {
3077
3077
  "id": "newsletter",
3078
- "description": "Use when running an email newsletter as a recurring publication — writing the subject line + preview text, structuring an issue so opens turn into clicks, the welcome/onboarding sequence, send cadence and engagement segmentation, growth loops (referral, signup incentive, double opt-in), and a metric scorecard that survives Apple Mail Privacy Protection. Triggers: 'write the newsletter subject line', 'my newsletter gets opened but nobody clicks', 'set up a welcome sequence', 'grow my newsletter list', 'newsletter referral program', 'how often should I send', 'what metrics matter now that opens are fake', 'click-to-open rate', 'escriu la newsletter d'aquesta setmana', 'campaña de newsletter que convierta'. NOT the one-off product launch or nurture campaign (that is marketing), NOT the SPF/DKIM/DMARC plumbing under the send (that is email-deliverability).",
3078
+ "description": "Use when running an email newsletter as a recurring publication — subject + preview pair, issues that turn opens into clicks, the welcome sequence, cadence and engagement tiering, growth loops, and a post-Apple-MPP click scorecard. NOT one-off launch or nurture sends (that is `marketing`), NOT SPF/DKIM/DMARC (that is `email-deliverability`).",
3079
3079
  "tags": [
3080
3080
  "newsletter",
3081
3081
  "email",
@@ -3609,7 +3609,7 @@
3609
3609
  },
3610
3610
  {
3611
3611
  "id": "prompt-engineering",
3612
- "description": "Use when one prompt has to give the same right answer across reruns, models, and hostile inputs — a prompt that works sometimes, forcing valid JSON or a fixed schema out of a model, choosing how many few-shot examples and which ones, hardening a prompt against injected instructions, writing a tiny eval set before changing a prompt, or porting a prompt to a new model without behavior drift. Triggers: 'the prompt works sometimes', 'force valid JSON from the model', 'how many few-shot examples', 'outputs drift between reruns', 'the model ignores my instructions on long inputs', 'users can paste instructions into my input field', 'el prompt a veces falla', 'forzar JSON válido del modelo', 'el model no segueix les instruccions'. NOT the agent loop, tool wiring, or RAG retrieval (that is building-agents).",
3612
+ "description": "Use when one prompt must give the same right answer across reruns, models, and pasted-in hostile input: forcing a fixed schema, picking the few-shot set, ordering the prompt blocks, or the inline cases you run while tuning. NOT the agent loop, tools, or retrieval (that is `building-agents`), NOT a standing CI eval harness (that is `agent-eval`).",
3613
3613
  "tags": [
3614
3614
  "prompts",
3615
3615
  "llm",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ericrisco/rsc",
3
- "version": "0.1.53",
3
+ "version": "0.1.54",
4
4
  "description": "Eric Risco's agent-skills catalog as a granular, self-recommending CLI installer.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lead-gen
3
- description: "Use when you need to find and qualify prospects, build a target list, or score and prioritize leads before anyone reaches out — defining an ICP, sourcing named accounts/contacts from Apollo/ZoomInfo/Clay, deduping against the CRM, and ranking with a fit+intent+engagement model. Triggers: 'build me a prospect list', 'who should we sell to', 'score these leads', 'which accounts do we call first', 'tighten our ICP', 'is this cold list GDPR-safe', 'necesito una lista de clientes potenciales', 'califica estos leads', 'a qui truquem primer'. NOT writing or sending the outreach (that is cold-outreach), NOT tracking the deal after first contact (that is sales-pipeline)."
3
+ description: "Use when building and qualifying a prospect list before anyone reaches out — a falsifiable ICP, named accounts/contacts from Apollo/ZoomInfo/Clay, deduped against the CRM, tiered by fit+intent+engagement. NOT writing or sending the outreach (that is cold-outreach), NOT tracking the deal after first contact (that is sales-pipeline)."
4
4
  tags: [lead-generation, prospecting, icp, lead-scoring, sales]
5
5
  recommends: [cold-outreach, sales-pipeline, market-research, data-scraper, spreadsheet-ops, email-deliverability, gdpr-privacy]
6
6
  origin: risco
@@ -8,9 +8,7 @@ origin: risco
8
8
 
9
9
  # Lead Gen — The List and the Model That Ranks It
10
10
 
11
- *You turn "we sell X to Y" into a deduplicated, scored, compliance-cleared roster of named accounts and people. You define the target, you build the list, you rank it — then you stop. You do not write the email and you do not run the deal.*
12
-
13
- The identity of this skill is **the list and its scoring model**, not the messages sent to it and not the pipeline it becomes. Everything you produce is a *prioritized roster + the rationale that ranked it*. The hand-off is the finish line, not the campaign.
11
+ *You turn "we sell X to Y" into a deduplicated, scored, compliance-cleared roster of named accounts and people. You define the target, you build the list, you rank it — then you stop. What you produce is a prioritized roster plus the rationale that ranked it; the hand-off is the finish line, not the campaign.*
14
12
 
15
13
  ## The pipeline — three phases, two gates
16
14
 
@@ -151,5 +149,3 @@ This skill stops at a scored, compliance-cleared list. From there:
151
149
  - The **A/B tiers + persona context** go to `../cold-outreach/SKILL.md` — that skill writes the message and the cadence; you do not.
152
150
  - **Accepted leads** (worked and responsive) go to `../sales-pipeline/SKILL.md` — that skill tracks stages, forecasts, and manages the deal; you do not.
153
151
  - If the request is really "how big is this market / which segment?" with no named list, that is `../market-research/SKILL.md`, not this skill.
154
-
155
- When the deliverable would be a message, a pipeline stage, or a market sizing — route. Your job ended at the ranked roster.
@@ -10,9 +10,9 @@ should_trigger:
10
10
  - prompt: "Is this cold prospect list legal to email under GDPR before we send?"
11
11
  why: "The compliance gate (GDPR LIA, no scraped basis) is part of making a list ship-ready — non-obvious that lead-gen owns it, not a generic legal skill."
12
12
  - prompt: "Necesito una lista de clientes potenciales para nuestro SaaS de logística."
13
- why: "Spanish core trigger — build a target list of prospects."
13
+ why: "Spanish-language phrasing of the core case — build a target list of prospects."
14
14
  - prompt: "A qui de la nostra base truquem primer, tenim 300 comptes sense prioritzar?"
15
- why: "Catalan trigger — scoring/tiering an unprioritized account list."
15
+ why: "Catalan-language phrasing — scoring/tiering an unprioritized account list."
16
16
 
17
17
  should_not_trigger:
18
18
  - prompt: "Write the cold email sequence for these prospects."
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: linkedin-carousels
3
- description: "Use when designing a LinkedIn carousel / document post — the swipeable multi-page PDF that is currently the highest-reach native LinkedIn format — and you need the slide-by-slide build: a scroll-stopping cover hook, a narrative arc that pulls swipe-to-swipe, one focused idea per slide with real visual hierarchy, a payoff + CTA closer, and a PDF export spec. Triggers: 'turn this into a LinkedIn carousel', 'design a swipeable PDF document post', 'my carousel cover gets no swipes fix the hook', 'how many slides and what goes on each', 'restructure one-idea-per-slide', 'what size to export so it isnt cropped on mobile', 'convierte este post en un carrusel de LinkedIn', 'dissenya'm un carrusel de LinkedIn amb portada i CTA'. NOT the account/format plan (that is linkedin-strategy), NOT a text or single-image feed post (that is linkedin-content), NOT a spoken-to talk deck (that is presentations)."
3
+ description: "Use when building a LinkedIn carousel / document post — the swipeable multi-page PDF — slide by slide: cover hook, narrative arc, one idea per slide, CTA closer, PDF export spec. NOT the account/format plan (that is `linkedin-strategy`), NOT a text or single-image feed post (that is `linkedin-content`), NOT a 16:9 talk deck (that is `presentations`)."
4
4
  tags: [linkedin, carousel, document-post, slide-design, visual-hierarchy, hook, b2b, social-content]
5
5
  recommends: [linkedin-content, linkedin-strategy, brand-identity, brand-voice, presentations, social-publisher]
6
6
  origin: risco
@@ -8,16 +8,10 @@ origin: risco
8
8
 
9
9
  # LinkedIn carousels
10
10
 
11
- Design **one swipeable LinkedIn document post**: the cover hook, the narrative arc, one idea
12
- per slide, and the PDF export spec. You hand back a slide-by-slide build ready to assemble in
13
- Canva/Figma/Slides and a one-page design+export checklist.
14
-
15
- You do not own the account plan (which formats, cadence, niche — that is
16
- [`../linkedin-strategy/SKILL.md`](../linkedin-strategy/SKILL.md)), the words of a text or
17
- single-image feed post ([`../linkedin-content/SKILL.md`](../linkedin-content/SKILL.md)), the
18
- programmatic upload ([`../linkedin-api/SKILL.md`](../linkedin-api/SKILL.md)), or a spoken-to
19
- 16:9 talk deck ([`../presentations/SKILL.md`](../presentations/SKILL.md)). Your artifact is the
20
- *slides of a phone-read PDF* — sequence and visual hierarchy are the product.
11
+ Design **one swipeable LinkedIn document post**. Your artifact is the *slides of a phone-read
12
+ PDF* — sequence and visual hierarchy are the product — handed back as a slide-by-slide build
13
+ ready to assemble in Canva/Figma/Slides plus a one-page design+export checklist. Everything
14
+ adjacent (the account plan, the feed copy, the upload, a talk deck) routes out; see Handoffs.
21
15
 
22
16
  ## What you produce
23
17
 
@@ -27,34 +21,30 @@ programmatic upload ([`../linkedin-api/SKILL.md`](../linkedin-api/SKILL.md)), or
27
21
  - **A design + export spec** — canvas, safe area, type floor, PDF checklist (one page).
28
22
  - **A one-line caption starter** — the first feed line; full caption tuning routes out.
29
23
 
30
- Precondition: you need a topic, an angle, or a source (post/article). If the ask is the
31
- account plan or a block of feed copy, you are in the wrong skill — see the handoffs table.
24
+ Precondition: a topic, an angle, or a source (post/article). If the ask is the account plan or
25
+ a block of feed copy, you are in the wrong skill — see the handoffs table.
32
26
 
33
27
  ## Ground first
34
28
 
35
- A carousel inherits an identity; it does not invent one. Before you design slides:
36
-
37
- - **Read the brand kit** if it exists in `02-DOCS/` (colors, type, logo) —
38
- [`../brand-identity/SKILL.md`](../brand-identity/SKILL.md) owns it. Don't pick arbitrary fonts.
39
- - **Read the voice** so the headlines sound like the account —
40
- [`../brand-voice/SKILL.md`](../brand-voice/SKILL.md) owns it.
41
- - **Pull the angle** from any plan/post already produced by
42
- [`../linkedin-strategy/SKILL.md`](../linkedin-strategy/SKILL.md) or
43
- [`../linkedin-content/SKILL.md`](../linkedin-content/SKILL.md). Reuse the hook, don't reopen it.
44
-
45
- If none exist, name your assumptions on slide 0 of the spec and proceed — don't stall.
29
+ A carousel inherits an identity; it does not invent one. Read the brand kit (colors, type,
30
+ logo — owned by [`../brand-identity/SKILL.md`](../brand-identity/SKILL.md)) and the voice
31
+ ([`../brand-voice/SKILL.md`](../brand-voice/SKILL.md)) from `02-DOCS/` if they exist; don't pick
32
+ arbitrary fonts. Pull the angle from any plan or post already produced by
33
+ [`../linkedin-strategy/SKILL.md`](../linkedin-strategy/SKILL.md) or
34
+ [`../linkedin-content/SKILL.md`](../linkedin-content/SKILL.md) — reuse the hook, don't reopen
35
+ it. If none exist, name your assumptions on slide 0 of the spec and proceed; don't stall.
46
36
 
47
37
  ## The swipe economics (why every rule below exists)
48
38
 
49
39
  Document/carousel posts are the **highest-engagement native format on LinkedIn right now** —
50
- they hit roughly 6.6% average engagement, ahead of every other format, and top-performing
51
- pages post far more of them than median pages. The reason is **dwell time**: a swipeable deck
52
- holds the thumb on screen, and dwell — not likes — is the algorithm's main distribution signal.
40
+ roughly 6.6% average engagement, ahead of every other format, and top-performing pages post far
41
+ more of them than median pages. The reason is **dwell time**: a swipeable deck holds the thumb
42
+ on screen, and dwell — not likes — is the algorithm's main distribution signal.
53
43
 
54
44
  So the whole bet is the **cover slide and the swipe-to-slide-2 bounce**. If the cover doesn't
55
- earn the first swipe, your slide count, your arc, and your CTA never get seen. Every swipe
56
- after that extends dwell and signals quality, which is why each slide must *pull to the next*.
57
- Design backwards from that: stop the thumb, then keep it moving.
45
+ earn the first swipe, your slide count, your arc, and your CTA never get seen; every swipe after
46
+ that extends dwell and signals quality, which is why each slide must *pull to the next*. Design
47
+ backwards from that: stop the thumb, then keep it moving.
58
48
 
59
49
  ## The cover slide
60
50
 
@@ -150,11 +140,10 @@ Good — one idea, one dominant element, breathing room
150
140
  ## Slide count
151
141
 
152
142
  Aim for the **6–12 band, ~8 as the sweet spot** (cover + ~6 content + CTA). Reported peaks
153
- cluster around 7–8 slides; 8–12 is where the highest dwell/save/share rates show up. Fewer
154
- than 5 underdelivers (not worth the swipe); more than ~15 loses people before the payoff.
155
-
156
- Treat the band as a guide, not a law: **length follows the arc, not a quota.** If the arc
157
- resolves in 7 slides, ship 7 — don't pad to hit a number.
143
+ cluster around 7–8 slides; 8–12 is where the highest dwell/save/share rates show up. Fewer than
144
+ 5 underdelivers (not worth the swipe); more than ~15 loses people before the payoff. Treat the
145
+ band as a guide, not a law: **length follows the arc, not a quota** — if the arc resolves in 7
146
+ slides, ship 7, don't pad to hit a number.
158
147
 
159
148
  ## The CTA closer
160
149
 
@@ -184,17 +173,17 @@ Gotchas: open the exported PDF and verify fonts — free Canva silently substi
184
173
  ```
185
174
 
186
175
  Portrait 4:5 takes the most vertical space in a mobile feed, which raises dwell and the chance
187
- of a scroll-stop. PDF is the only export that preserves fonts and layout reliably across
188
- devices — exporting slides as images loses crispness and breaks selectable text. The full
176
+ of a scroll-stop; PDF is the only export that preserves fonts and layout reliably across
177
+ devices, since slides exported as images lose crispness and break selectable text. The full
189
178
  checklist in prose is in [`references/carousel-patterns.md`](references/carousel-patterns.md).
190
179
 
191
180
  ## The feed caption handoff
192
181
 
193
182
  A document post still has a **text caption above it**, and its first 1–2 lines (before the
194
183
  "…more" fold) must restate the cover hook — that line is what people read before deciding to
195
- expand and swipe. Give a one-line starter that echoes the cover, then route full feed-copy
196
- length/tone tuning to [`../linkedin-content/SKILL.md`](../linkedin-content/SKILL.md). You own
197
- the slides; that sibling owns the caption.
184
+ expand and swipe. Give a one-line starter that echoes the cover; you own the slides, and
185
+ [`../linkedin-content/SKILL.md`](../linkedin-content/SKILL.md) owns the caption's full
186
+ length/tone tuning.
198
187
 
199
188
  ## Handoffs
200
189
 
@@ -202,7 +191,7 @@ the slides; that sibling owns the caption.
202
191
  |---|---|
203
192
  | The account/format plan, cadence, niche, who to target | [`../linkedin-strategy/SKILL.md`](../linkedin-strategy/SKILL.md) |
204
193
  | A text or single-image feed post (just the copy) | [`../linkedin-content/SKILL.md`](../linkedin-content/SKILL.md) |
205
- | 1:1 DMs / connection-request outreach sequences | `linkedin-outreach` |
194
+ | 1:1 DMs / connection-request outreach sequences | [`../linkedin-outreach/SKILL.md`](../linkedin-outreach/SKILL.md) |
206
195
  | To publish/schedule the deck via the LinkedIn API | [`../linkedin-api/SKILL.md`](../linkedin-api/SKILL.md) |
207
196
  | A spoken-to 16:9 talk deck (speaker support) | [`../presentations/SKILL.md`](../presentations/SKILL.md) |
208
197
  | The color / type / logo brand kit the deck is styled in | [`../brand-identity/SKILL.md`](../brand-identity/SKILL.md) |
@@ -236,4 +225,4 @@ scripts/verify.sh path/to/carousel-spec.md
236
225
  It checks (read-only) for a labeled cover slide, a slide count in 5–15 (warns outside 6–12), a
237
226
  CTA slide with an explicit ask, a portrait/square canvas, a ≥28 px type floor, "PDF" as the
238
227
  export target, and warns on any crammed (3+ bullet) interior slide. An empty or clean target
239
- passes. The deeper rigor is the capability eval in `evals/`.
228
+ passes.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: llm-pipeline
3
- description: "Use when wiring several LLM calls into one production flow, when random 429s/timeouts/provider outages take a feature down, when adding a fallback model or a gateway in front of OpenAI/Claude, or when the bill explodes from uncached or flagship-everywhere calls. Triggers: 'chain these LLM calls', 'step 1 extracts step 2 summarizes', 'add a fallback if GPT fails use Claude', 'route easy requests to Haiku escalate to Opus', 'put a LiteLLM gateway in front', 'our bill tripled because we re-call the model on every request', 'semantic cache the responses', 'encadenar llamadas y cachear respuestas', 'cadena de crides a l'LLM amb fallback'. NOT prompt wording (that is prompt-engineering)."
3
+ description: "Use when wiring several LLM calls into a production flow: typed contracts between steps, a router/gateway so 429s, timeouts and outages fail over instead of taking you down, and cost control via caching, model tiers and abort caps. NOT single-prompt wording (that is `prompt-engineering`), NOT a model-driven tool loop (that is `building-agents`)."
4
4
  tags: [llm-orchestration, llm-gateway, fallbacks, prompt-caching, cost-control, litellm, reliability]
5
5
  recommends: [prompt-engineering, structured-extraction, building-agents, cost-tracking, agent-eval, rag, observability, parallel]
6
6
  origin: risco
@@ -10,14 +10,7 @@ origin: risco
10
10
 
11
11
  Wire multiple LLM calls into a reliable, controllable production pipeline. You chain steps where one call's validated output feeds the next, put a router in front of providers so an outage fails over instead of taking you down, and engineer the cross-cutting concerns: timeouts, bounded retries, fallbacks, caching, and cost caps.
12
12
 
13
- ## Core stance
14
-
15
- Treat the LLM as an unreliable network dependency, not a local function call. Everything below follows from that.
16
-
17
- - **Every call gets a hard timeout and bounded retries.** Providers have outages, rate limits, and latency tails; a naked call can hang your whole request behind one slow upstream.
18
- - **Steps pass validated structured objects, not free text.** The output of step N is a contract you assert on before it becomes step N+1's input — a parse failure is caught at the seam, not three steps later.
19
- - **A router sits in front of every provider.** One model's 429/500/timeout fails over to another; no single provider is a single point of failure.
20
- - **Cache and tier before you tune prompts.** The cheapest, fastest, most reliable call is the one you never made. Prompt wording is the last lever, not the first.
13
+ Treat the LLM as an unreliable network dependency, not a local function call. Every rule below follows from that: providers have outages, rate limits, and latency tails, so no single provider is a single point of failure and no call is allowed to run unbounded.
21
14
 
22
15
  ## Do you even need a pipeline?
23
16
 
@@ -116,6 +109,8 @@ except Exception:
116
109
 
117
110
  ## Caching: two distinct layers
118
111
 
112
+ The cheapest, fastest, most reliable call is the one you never made — so cache and tier before you tune prompts. Wording is the last lever, not the first.
113
+
119
114
  | Layer | What it matches | Safety | Enable when |
120
115
  | --- | --- | --- | --- |
121
116
  | Prefix / prompt cache (provider-native) | Exact prefix of the prompt | Always safe (same input → same cached compute) | Always; put the stable prefix first |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: modal
3
- description: "Use when running Python functions or GPU workloads serverlessly on Modal — defining a modal.App with inline container Images, scaling @app.function onto CPU/GPU, persisting weights or datasets in a Volume, scheduling jobs, serving an HTTP/ASGI endpoint, or choosing modal run vs serve vs deploy. Triggers: 'run my embedding job on an H100 without managing servers', 'cache HuggingFace weights across runs', 'my @app.function GPU string errors', 'gpu=modal.gpu.A100() fails', 'modal serve isn't hot-reloading my fastapi_endpoint', 'cold start too slow / keep a warm pool', 'ejecutar Python en GPU serverless', 'desplegar un model de difusió amb GPU sense servidor i exposar-lo per HTTP'. NOT managed prediction endpoints with no infra code (that is replicate) and NOT persistent SSH-able GPU pods rented by the hour (that is runpod)."
3
+ description: "Use when running Python or GPU workloads serverlessly on Modal — modal.App, inline container Images, gpu= on @app.function, Volumes for weight caching, Cron schedules, ASGI endpoints, modal run vs serve vs deploy. NOT managed prediction APIs with no container of your own (that is replicate); NOT SSH-able GPU boxes rented by the hour (that is runpod)."
4
4
  tags: [modal, serverless, gpu, python, ai-infra, deployment, cron, web-endpoint]
5
5
  recommends: [replicate, runpod, fastapi, docker, python, llm-pipeline]
6
6
  origin: risco
@@ -19,27 +19,19 @@ Pinned stack: **modal 1.4.3** (released 2026-05-18), Python **3.10–3.14** (`>=
19
19
  Install with `pip install modal` then `modal setup` to authenticate. Everything below uses
20
20
  the Modal 1.0+ API; several pre-1.0 forms were removed and are called out as Bad→Good.
21
21
 
22
- ## When to use
22
+ ## Not this skill
23
23
 
24
- - Running a Python function or batch job on remote CPU/GPU with no server to manage.
25
- - GPU inference, fine-tuning, or model serving (vLLM, diffusion, embeddings) on T4…B200.
26
- - Building a container image inline (`Image.debian_slim().uv_pip_install(...)`) for a remote job.
27
- - Persisting model weights or datasets across runs with a Modal `Volume`.
28
- - Scheduled jobs (nightly report, periodic scrape) via `modal.Cron` / `modal.Period`.
29
- - Exposing a function over HTTP (`fastapi_endpoint`, `asgi_app`, `wsgi_app`, `web_server`).
30
- - Fan-out parallelism with `.map()` / `.starmap()` / `.spawn()`.
24
+ Modal owns the serverless-container-as-decorators surface and its CLI lifecycle; the *contents*
25
+ of your function belong elsewhere.
31
26
 
32
- ## When NOT to use
33
-
34
- - Calling a **managed prediction API** with no container of your own → **`replicate`** / `together-fireworks` / `fal`.
35
- - Renting a **persistent, SSH-able GPU box** by the hour/week → **`runpod`**.
36
- - Generic **FastAPI design** (routing, Pydantic, deps) independent of host → **`fastapi`**.
37
- - Writing a **Dockerfile** for a registry / k8s / Compose → **`docker`**.
38
- - General **Python language/runtime** questions → **`python`**.
39
- - **RAG / LLM pipeline** orchestration logic itself → **`llm-pipeline`**.
40
-
41
- Modal owns the serverless-container-as-decorators surface and its CLI lifecycle; the
42
- *contents* of your function (FastAPI app, RAG chain) belong to the siblings above.
27
+ | The job | Goes to |
28
+ |---|---|
29
+ | Calling a **managed prediction API** with no container of your own | [`replicate`](../replicate/SKILL.md) / [`together-fireworks`](../together-fireworks/SKILL.md) / [`fal`](../fal/SKILL.md) |
30
+ | Renting a **persistent, SSH-able GPU box** by the hour/week | [`runpod`](../runpod/SKILL.md) |
31
+ | **FastAPI design** (routing, Pydantic, deps) independent of host | [`fastapi`](../fastapi/SKILL.md) |
32
+ | Writing a **Dockerfile** for a registry / k8s / Compose | [`docker`](../docker/SKILL.md) |
33
+ | General **Python language/runtime** questions | [`python`](../python/SKILL.md) |
34
+ | **RAG / LLM pipeline** orchestration logic itself | [`llm-pipeline`](../llm-pipeline/SKILL.md) |
43
35
 
44
36
  ## Decision: which entrypoint?
45
37
 
@@ -109,8 +101,8 @@ image = (
109
101
  )
110
102
  ```
111
103
 
112
- `→ references/images-gpu-cookbook.md` for vLLM / torch+CUDA / diffusers recipes and the
113
- download-once weight-cache pattern.
104
+ → [`references/images-gpu-cookbook.md`](references/images-gpu-cookbook.md) for vLLM / torch+CUDA
105
+ / diffusers recipes and the download-once weight-cache pattern.
114
106
 
115
107
  ## GPU — it's a string now
116
108
 
@@ -193,8 +185,7 @@ def pull():
193
185
  ```
194
186
 
195
187
  Never bake a token into the image (`.run_commands("export TOKEN=...")`) — it's recorded in
196
- layer history. Use a Secret. `→ references/images-gpu-cookbook.md` for the weight-cache and
197
- HF/OpenAI secret patterns.
188
+ layer history. Use a Secret. The cookbook above also carries the HF/OpenAI secret patterns.
198
189
 
199
190
  ## Web endpoints
200
191
 
@@ -228,8 +219,8 @@ def web():
228
219
 
229
220
  Develop with `modal serve app.py` (hot-reload); ship with `modal deploy app.py` (stable URL).
230
221
  For custom domains, proxy-auth tokens, batching (`@modal.batched`), and concurrency tuning →
231
- `references/web-and-scaling.md`. For the FastAPI app's *own* design (routes, Pydantic, deps),
232
- that's the `fastapi` sibling — this skill only mounts it.
222
+ [`references/web-and-scaling.md`](references/web-and-scaling.md). For the FastAPI app's *own*
223
+ design (routes, Pydantic, deps), that's [`fastapi`](../fastapi/SKILL.md) — this skill only mounts it.
233
224
 
234
225
  ## Scheduled jobs
235
226
 
@@ -268,9 +259,9 @@ def main():
268
259
  they complete (faster when latencies vary). Combine with `retries=` on the function so a
269
260
  single bad input doesn't sink the batch.
270
261
 
271
- ## Anti-patterns → STOP
262
+ ## Anti-patterns
272
263
 
273
- | Rationalization | Reality → STOP |
264
+ | Anti-pattern | Do instead |
274
265
  |---|---|
275
266
  | "I'll use `gpu=modal.gpu.A100()` like the old docs" | Removed in 1.0. Use the string `gpu="A100-80GB"`. |
276
267
  | "Attach a GPU, it might speed up this CPU job" | GPU is billed per second alive. CPU-only job → no `gpu=`. |
@@ -279,30 +270,21 @@ single bad input doesn't sink the batch.
279
270
  | "`modal run` it, the endpoint/schedule will stay up" | `run` is ephemeral; it exits. Use `modal deploy` for anything persistent. |
280
271
  | "Order the decorators however — Modal figures it out" | `@app.function` outermost, web decorator innermost. Wrong order errors. |
281
272
  | "Bake the HF token into the image with `run_commands`" | Leaks into layer history. Use `modal.Secret.from_name(...)`. |
282
- | "Just call the model via a managed API through Modal" | If you write no container, that's a managed-API job → `replicate`. |
283
- | "I need a box to SSH into for a week" | That's a persistent rental → `runpod`, not Modal's scale-to-zero. |
273
+ | "Just call the model via a managed API through Modal" | If you write no container, that's a managed-API job → [`replicate`](../replicate/SKILL.md). |
274
+ | "I need a box to SSH into for a week" | That's a persistent rental → [`runpod`](../runpod/SKILL.md), not Modal's scale-to-zero. |
284
275
  | "Set `min_containers` high so it's always fast" | Idle warm containers cost money 24/7. Tune `scaledown_window` first. |
285
276
 
286
- ## verify.sh
277
+ ## Verify
287
278
 
288
- `scripts/verify.sh [TARGET]` statically lints the nearest emitted Modal `*.py`: it requires a
289
- `modal.App(`, **fails** if the removed `modal.gpu.` object form appears, checks that any web
290
- decorator sits under an `@app.function`, and that any `Volume` uses
279
+ [`scripts/verify.sh`](scripts/verify.sh) `[TARGET]` statically lints the nearest emitted Modal
280
+ `*.py`: it requires a `modal.App(`, **fails** if the removed `modal.gpu.` object form appears,
281
+ checks that any web decorator sits under an `@app.function`, and that any `Volume` uses
291
282
  `from_name(..., create_if_missing=...)`. It runs `python -c "import modal"` only if modal is
292
- installed (skip-pass otherwise) and needs **no Modal credentials**. On an empty/clean target it
293
- exits 0.
294
-
295
- ## Project grounding (02-DOCS + CLAUDE.md)
296
-
297
- In a project with a `02-DOCS/` layer (the [`harness`](../harness/SKILL.md) wiki), record this
298
- app's real Modal choices — GPU types, image base, Volume names, schedule, endpoint shape — in
299
- `02-DOCS/wiki/stack/modal.md` and index it in `02-DOCS/wiki/index.md` (the Knowledge map; root
300
- `CLAUDE.md` keeps only a short pointer to it). Read it
301
- first on every use; create/update it with the real decisions. No `02-DOCS/`? Skip silently.
283
+ installed (skip-pass otherwise), needs **no Modal credentials**, and exits 0 on an empty target.
302
284
 
303
- ## See Also
285
+ ## Project grounding (02-DOCS)
304
286
 
305
- - [`fastapi`](../fastapi/SKILL.md) — the design of the FastAPI app you mount behind `@modal.asgi_app()`.
306
- - References: [`references/images-gpu-cookbook.md`](references/images-gpu-cookbook.md), [`references/web-and-scaling.md`](references/web-and-scaling.md).
307
- - Verify gate: [`scripts/verify.sh`](scripts/verify.sh).
308
- - Siblings (catalog): `replicate` / `together-fireworks` / `fal` (managed prediction APIs), `runpod` (persistent GPU pods), `docker` (Dockerfiles), `python` (language), `llm-pipeline` (orchestration).
287
+ In a project with a `02-DOCS/` layer (the [`harness`](../harness/SKILL.md) wiki), read
288
+ `02-DOCS/wiki/stack/modal.md` first, then record this app's real Modal choices there — GPU types,
289
+ image base, Volume names, schedule, endpoint shape — and index it in `02-DOCS/wiki/index.md`. No
290
+ `02-DOCS/`? Skip silently.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: newsletter
3
- description: "Use when running an email newsletter as a recurring publication — writing the subject line + preview text, structuring an issue so opens turn into clicks, the welcome/onboarding sequence, send cadence and engagement segmentation, growth loops (referral, signup incentive, double opt-in), and a metric scorecard that survives Apple Mail Privacy Protection. Triggers: 'write the newsletter subject line', 'my newsletter gets opened but nobody clicks', 'set up a welcome sequence', 'grow my newsletter list', 'newsletter referral program', 'how often should I send', 'what metrics matter now that opens are fake', 'click-to-open rate', 'escriu la newsletter d'aquesta setmana', 'campaña de newsletter que convierta'. NOT the one-off product launch or nurture campaign (that is marketing), NOT the SPF/DKIM/DMARC plumbing under the send (that is email-deliverability)."
3
+ description: "Use when running an email newsletter as a recurring publication — subject + preview pair, issues that turn opens into clicks, the welcome sequence, cadence and engagement tiering, growth loops, and a post-Apple-MPP click scorecard. NOT one-off launch or nurture sends (that is `marketing`), NOT SPF/DKIM/DMARC (that is `email-deliverability`)."
4
4
  tags: [newsletter, email, growth, copywriting, retention-metrics]
5
5
  recommends: [marketing, email-deliverability, brand-voice, landing-copy, ab-testing]
6
6
  profiles: []
@@ -11,29 +11,19 @@ origin: risco
11
11
 
12
12
  Run the newsletter as a **product you ship on a cadence**, not a one-off send. The job is the system around the recurring issue: the subject + preview that earns the open, the issue body that earns the click, the welcome sequence that activates a new subscriber, the cadence and segmentation that keep the list healthy, the growth loops that compound it, and a scorecard that still tells the truth after Apple broke open rates. Every send is one episode of an ongoing show — design the show, not the episode.
13
13
 
14
- ## When to use
15
-
16
- - Writing the subject line + preview text for an issue and fitting them to inbox truncation.
17
- - Structuring a recurring issue so opens convert: hook on the first screen, scannable body, one CTA.
18
- - Writing the welcome / onboarding sequence a confirmed subscriber gets.
19
- - Planning send cadence, frequency, and engagement-based segmentation.
20
- - Designing a growth loop: referral program, signup incentive / lead magnet, double opt-in.
21
- - Choosing which metrics to trust now that Apple MPP inflates opens; building the scorecard.
22
- - Rescuing a newsletter with high opens but no clicks, or a quietly decaying engaged-reader count.
23
-
24
14
  ## When NOT to use — route instead
25
15
 
26
16
  | The ask | Route to |
27
17
  |---|---|
28
18
  | One-off product launch announcement or campaign drip nurture | `../marketing/SKILL.md` |
29
- | Mail lands in spam; set up SPF / DKIM / DMARC, tracking domain, reputation | `email-deliverability` |
19
+ | Mail lands in spam; set up SPF / DKIM / DMARC, tracking domain, reputation | `../email-deliverability/SKILL.md` |
30
20
  | Write the subscribe / opt-in landing page copy | `../landing-copy/SKILL.md` |
31
21
  | Define the house voice, tone, and vocabulary the newsletter speaks in | `../brand-voice/SKILL.md` |
32
- | Win back / reactivate lapsed *paying customers* (lifecycle, not readers) | `retention` |
22
+ | Win back / reactivate lapsed *paying customers* (lifecycle, not readers) | `../retention/SKILL.md` |
33
23
  | Produce the underlying long-form articles the issue links out to | `../content-engine/SKILL.md` |
34
- | Sample size / significance / MDE math for the test itself | `ab-testing` |
35
- | Source or scrape new contacts; prospect an un-opted-in list | `lead-gen`, `../cold-outreach/SKILL.md` |
36
- | Actually wire the send through an ESP / Gmail API and schedule it | `email-connector`, `google-workspace` |
24
+ | Sample size / significance / MDE math for the test itself | `../ab-testing/SKILL.md` |
25
+ | Source or scrape new contacts; prospect an un-opted-in list | `../lead-gen/SKILL.md`, `../cold-outreach/SKILL.md` |
26
+ | Actually wire the send through an ESP / Gmail API and schedule it | `../email-connector/SKILL.md`, `../google-workspace/SKILL.md` |
37
27
 
38
28
  You own the *recurring opted-in publication and its open/click/growth system*. The plumbing under every send and the page that captures the signup are someone else's.
39
29
 
@@ -81,7 +71,7 @@ The subject and the preview (preheader) ship together and are tested together
81
71
  - **Payload in the first ~33 characters**; keep the whole subject ~30–50 chars (≈7–9 words) so it survives mobile truncation.
82
72
  - **The preview extends the subject, it never repeats it.** Its first ~35–50 chars are prime real estate; waste them on a duplicate and you've burned the line.
83
73
  - **≤2 emojis, at the end, never an all-emoji subject** — an all-emoji subject is the one case that actually trips filters.
84
- - **The "spam trigger words" list is a myth.** "Free", "guarantee", a normal emoji — these do not sink you; authentication and sender reputation dominate deliverability. Police reputation, not vocabulary; the reputation/auth layer lives in `email-deliverability`.
74
+ - **The "spam trigger words" list is a myth.** "Free", "guarantee", a normal emoji — these do not sink you; authentication and sender reputation dominate deliverability. Police reputation, not vocabulary; the reputation/auth layer lives in `../email-deliverability/SKILL.md`.
85
75
 
86
76
  ```text
87
77
  Bad (payload past char 33, preview repeats subject):
@@ -134,13 +124,13 @@ A newsletter is the canonical bulk marketing message, so the Gmail/Yahoo bulk-se
134
124
  - **RFC 8058 one-click unsubscribe** (`List-Unsubscribe` + `List-Unsubscribe-Post` headers) on every send, plus a **visible footer unsubscribe link.** Both, always.
135
125
  - **Keep the spam-complaint rate under 0.1%** and never let it reach 0.3%. This is why you sunset, not why you mail harder.
136
126
 
137
- The DNS / authentication side of those rules — SPF, DKIM, DMARC, the sending domain — is **not this skill**; that is `email-deliverability`. This skill applies the rules to the issue and the cadence.
127
+ The DNS / authentication side of those rules — SPF, DKIM, DMARC, the sending domain — is **not this skill**; that is `../email-deliverability/SKILL.md`. This skill applies the rules to the issue and the cadence.
138
128
 
139
129
  ## A/B testing the right way
140
130
 
141
131
  - **Test exactly one element at a time** — subject vs subject, or preview vs preview. Change two and the winner is uninterpretable.
142
132
  - **Put preview text in the rotation**, not just the subject; it's half the inbox row and usually under-tested.
143
- - The statistical design — sample size, significance, minimum detectable effect — is `ab-testing`. This skill tells you *what* to test; that one tells you whether the result is real.
133
+ - The statistical design — sample size, significance, minimum detectable effect — is `../ab-testing/SKILL.md`. This skill tells you *what* to test; that one tells you whether the result is real.
144
134
 
145
135
  ## Anti-patterns
146
136
 
@@ -151,7 +141,7 @@ The DNS / authentication side of those rules — SPF, DKIM, DMARC, the sending d
151
141
  | Preview text repeats the subject | Burns half the inbox row on a duplicate | Preview extends the subject with new info |
152
142
  | Mailing a decaying list harder | Complaints climb; reputation and inbox placement collapse | Sunset / re-permission the dormant tier |
153
143
  | All-emoji subject line | The one emoji case that actually trips filters | ≤2 emojis, at the end, around real words |
154
- | Policing "spam trigger words" | A myth; reputation/auth decide deliverability | Fix auth + reputation in `email-deliverability` |
144
+ | Policing "spam trigger words" | A myth; reputation/auth decide deliverability | Fix auth + reputation in `../email-deliverability/SKILL.md` |
155
145
  | Buying a list / no double opt-in | Spam traps and complaints gate the whole sender | Double opt-in; grow with referral + lead magnet |
156
146
  | Testing two variables at once | Winner is uninterpretable | One variable; preview in the rotation |
157
147
  | Referral ask bolted on months later | Misses peak engagement | Put the ask inside the welcome sequence |
@@ -23,7 +23,7 @@ tiering. Numbers below are dated; treat them as calibration, not promises.
23
23
  generic "join our newsletter."
24
24
  - The asset doubles as shareable bait for the referral loop — make it good
25
25
  enough to forward.
26
- - The opt-in *page* and its copy are `../landing-copy/SKILL.md`; this skill owns
26
+ - The opt-in *page* and its copy are `../../landing-copy/SKILL.md`; this skill owns
27
27
  what the incentive is and how it ties into the welcome + referral flow.
28
28
 
29
29
  ## Opt-in: single vs double
@@ -64,10 +64,10 @@ this? click to stay") and, if no click, a **sunset** off the active list.
64
64
  is the lever that protects it. (Yahoo Sender Hub best practices; Google
65
65
  Workspace sender guidelines — accessed 2026-06-02.)
66
66
  - Re-permission is a newsletter-list hygiene step. Lifecycle reactivation of
67
- lapsed *paying customers* is a different job — that is `retention`.
67
+ lapsed *paying customers* is a different job — that is `../../retention/SKILL.md`.
68
68
 
69
69
  ## Send-time hypothesis
70
70
 
71
71
  Tuesday/Thursday ~10am or 1–3pm is the cross-industry baseline starting point.
72
72
  It is a hypothesis to test against your own list's click data, never a fixed law.
73
- The test design (sample size, significance) is `ab-testing`.
73
+ The test design (sample size, significance) is `../../ab-testing/SKILL.md`.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: prompt-engineering
3
- description: "Use when one prompt has to give the same right answer across reruns, models, and hostile inputs — a prompt that works sometimes, forcing valid JSON or a fixed schema out of a model, choosing how many few-shot examples and which ones, hardening a prompt against injected instructions, writing a tiny eval set before changing a prompt, or porting a prompt to a new model without behavior drift. Triggers: 'the prompt works sometimes', 'force valid JSON from the model', 'how many few-shot examples', 'outputs drift between reruns', 'the model ignores my instructions on long inputs', 'users can paste instructions into my input field', 'el prompt a veces falla', 'forzar JSON válido del modelo', 'el model no segueix les instruccions'. NOT the agent loop, tool wiring, or RAG retrieval (that is building-agents)."
3
+ description: "Use when one prompt must give the same right answer across reruns, models, and pasted-in hostile input: forcing a fixed schema, picking the few-shot set, ordering the prompt blocks, or the inline cases you run while tuning. NOT the agent loop, tools, or retrieval (that is `building-agents`), NOT a standing CI eval harness (that is `agent-eval`)."
4
4
  tags: [prompts, llm, few-shot, structured-output, evals]
5
5
  recommends: [building-agents, agent-eval, structured-extraction]
6
6
  origin: risco
@@ -10,12 +10,6 @@ origin: risco
10
10
 
11
11
  You are tuning a single prompt so it produces the same correct output across reruns, across models, and against adversarial input. This is the craft layer — the prompt artifact itself: its block order, its few-shot set, its output contract, and the small eval that proves it. The systems layer (loop, tools, retrieval) is `../building-agents/SKILL.md`.
12
12
 
13
- ## The one rule
14
-
15
- > A prompt is not done until it passes a small eval set you wrote **before** you started tuning. Without cases you are fiddling — changing words and trusting a vibe. With 5-15 cases, every edit is a measurement.
16
-
17
- Write the cases first. They define "right answer" before you fall in love with a phrasing.
18
-
19
13
  ## Prompt skeleton (this order)
20
14
 
21
15
  Order the blocks so the model reads identity and task before it sees the (untrusted) input. Each block earns its place:
@@ -86,11 +80,11 @@ Good (range: normal / awkward / edge):
86
80
  - **Re-state the task after the input** for long inputs. Why: when the input is huge, early instructions fall out of attention — this is the cause of "the model ignores my instructions on long inputs".
87
81
  - **Phrase constraints positively.** "Output only the category" survives; "don't add commentary" invites the model to negotiate.
88
82
  - **Add a refusal anchor** — one explicit branch for out-of-contract input (`If the ticket is empty or unreadable, output: other`). Why: undefined behavior is where injections and drift live.
89
- - System-scope abuse handling — refusal policy, monitoring, jailbreak defense across a product — is `agent-safety`, not this skill. Here you harden one prompt.
83
+ - System-scope abuse handling — refusal policy, monitoring, jailbreak defense across a product — is `../agent-safety/SKILL.md`, not this skill. Here you harden one prompt.
90
84
 
91
- ## Inline evals (the part people skip)
85
+ ## Inline evals — write these first
92
86
 
93
- Build 5-15 cases next to the prompt and run them before AND after every change.
87
+ A prompt is not done until it passes a small eval set you wrote **before** you started tuning: 5-15 cases next to the prompt, run before AND after every change. Cases fix what "right answer" means before you fall in love with a phrasing — without them you are fiddling, changing words and trusting a vibe; with them every edit is a measurement.
94
88
 
95
89
  ```yaml
96
90
  # prompt-eval cases for the triage prompt
@@ -112,7 +106,7 @@ cases:
112
106
  expect: { equals: "billing" } # input treated as data, not command
113
107
  ```
114
108
 
115
- Assert on the contract: schema-valid, exact token, contains/not-contains. Keep them in the repo beside the prompt. The standing harness — golden set, LLM-as-judge, CI regression gate, metrics — is `agent-eval`; this is the small inline set you run while tuning.
109
+ Assert on the contract: schema-valid, exact token, contains/not-contains. Keep them in the repo beside the prompt; `references/eval-templates.md` has the cases.yaml shape, assertion helpers, and a before/after diff runner. The standing harness — golden set, LLM-as-judge, CI regression gate, metrics — is `../agent-eval/SKILL.md`; this is the small inline set you run while tuning.
116
110
 
117
111
  ## Iterate one variable at a time
118
112
 
@@ -131,8 +125,3 @@ Assert on the contract: schema-valid, exact token, contains/not-contains. Keep t
131
125
  | 3 near-identical few-shot examples | Teaches one shape, wastes tokens | 3 deliberately different: normal / awkward / edge |
132
126
  | Negative-only constraints ("don't…") | Invites negotiation, ignored on long input | Phrase positively; re-state task after long input |
133
127
  | Tuning by vibe, no cases | You are fiddling, not engineering | Write 5-15 cases first; measure each edit |
134
-
135
- ## References
136
-
137
- - `references/output-contracts.md` — per-provider strict-output recipes, schema surface (pydantic/zod), streaming caveat, retry-on-parse-fail loop.
138
- - `references/eval-templates.md` — cases.yaml shape, assertion helpers, before/after diff runner, DSPy MIPROv2-vs-GEPA when-to-optimize note.
@@ -10,7 +10,7 @@ should_trigger:
10
10
  - prompt: "Make this prompt enforce a fixed schema reliably instead of sometimes returning prose."
11
11
  why: "Forcing a fixed schema out of a model — the output-contract decision table (strict json_schema / strict tool use vs JSON mode)."
12
12
  - prompt: "Write me a small eval set to check this prompt before I change it."
13
- why: "Inline eval set authored before tuning — 'the one rule' of the skill; the small set, not a standing harness."
13
+ why: "Inline eval set authored before tuning — the discipline the 'Inline evals — write these first' section exists to enforce; the small set, not a standing harness."
14
14
  - prompt: "Users can paste 'ignore your instructions' into my input field and the model obeys it."
15
15
  why: "Prompt-scope injection hardening — delimiting untrusted input and treating it as data, a named robustness rule."
16
16
  - prompt: "I'm moving this prompt from one model to another and the behavior shifted; how do I keep it stable?"