@ericrisco/rsc 0.1.44 → 0.1.46

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.
Files changed (97) hide show
  1. package/README.md +1 -1
  2. package/manifest.json +110 -86
  3. package/package.json +1 -1
  4. package/scripts/lib/domains.js +1 -1
  5. package/scripts/skill-migration-brief.md +192 -0
  6. package/skills/ab-testing/SKILL.md +9 -41
  7. package/skills/accessibility/SKILL.md +5 -7
  8. package/skills/ads/SKILL.md +9 -24
  9. package/skills/agent-eval/SKILL.md +7 -33
  10. package/skills/agent-safety/SKILL.md +7 -14
  11. package/skills/ai-media/SKILL.md +4 -20
  12. package/skills/analytics/SKILL.md +8 -30
  13. package/skills/analyze/SKILL.md +24 -59
  14. package/skills/angular/SKILL.md +12 -25
  15. package/skills/api-connector-builder/SKILL.md +10 -27
  16. package/skills/api-design/SKILL.md +7 -14
  17. package/skills/article-writing/SKILL.md +1 -18
  18. package/skills/astro/SKILL.md +36 -54
  19. package/skills/author-skill/SKILL.md +41 -74
  20. package/skills/author-skill/evals/README.md +5 -5
  21. package/skills/author-skill/evals/cases.yaml +8 -8
  22. package/skills/author-skill/references/description-recipe.md +25 -26
  23. package/skills/author-skill/references/eval-authoring.md +1 -1
  24. package/skills/author-skill/references/rsc-conventions.md +1 -1
  25. package/skills/automation-flows/SKILL.md +6 -16
  26. package/skills/automation-strategy/SKILL.md +1 -9
  27. package/skills/aws-essentials/SKILL.md +6 -23
  28. package/skills/backups/SKILL.md +1 -7
  29. package/skills/bash-scripting/SKILL.md +5 -9
  30. package/skills/bookkeeping/SKILL.md +2 -10
  31. package/skills/brand-identity/SKILL.md +18 -44
  32. package/skills/brand-voice/SKILL.md +4 -31
  33. package/skills/building-agents/SKILL.md +20 -103
  34. package/skills/business-intelligence/SKILL.md +9 -23
  35. package/skills/calendar-scheduling/SKILL.md +11 -27
  36. package/skills/case-studies/SKILL.md +3 -8
  37. package/skills/chatbot/SKILL.md +6 -23
  38. package/skills/chrome-extension/SKILL.md +2 -2
  39. package/skills/clarify/SKILL.md +31 -72
  40. package/skills/clickhouse-analytics/SKILL.md +2 -8
  41. package/skills/client-onboarding/SKILL.md +17 -19
  42. package/skills/cloudflare/SKILL.md +3 -8
  43. package/skills/code-review/SKILL.md +10 -23
  44. package/skills/codebase-onboarding/SKILL.md +2 -7
  45. package/skills/cold-outreach/SKILL.md +9 -30
  46. package/skills/community/SKILL.md +4 -31
  47. package/skills/competitor-watch/SKILL.md +20 -35
  48. package/skills/compliance/SKILL.md +10 -37
  49. package/skills/compose-multiplatform/SKILL.md +1 -1
  50. package/skills/constitution/SKILL.md +8 -35
  51. package/skills/content-engine/SKILL.md +4 -16
  52. package/skills/context-budget/SKILL.md +3 -21
  53. package/skills/continuous-learning/SKILL.md +10 -40
  54. package/skills/contracts/SKILL.md +6 -17
  55. package/skills/coolify/SKILL.md +8 -14
  56. package/skills/cost-tracking/SKILL.md +3 -11
  57. package/skills/course-builder/SKILL.md +17 -45
  58. package/skills/course-storytelling/SKILL.md +26 -94
  59. package/skills/cpp/SKILL.md +26 -71
  60. package/skills/csharp-dotnet/SKILL.md +19 -38
  61. package/skills/customer-support/SKILL.md +14 -37
  62. package/skills/dashboard/SKILL.md +6 -26
  63. package/skills/data-cleaning/SKILL.md +37 -63
  64. package/skills/data-policy/SKILL.md +8 -21
  65. package/skills/data-scraper/SKILL.md +1 -7
  66. package/skills/debug/SKILL.md +10 -49
  67. package/skills/deployment/SKILL.md +38 -101
  68. package/skills/design/SKILL.md +34 -116
  69. package/skills/fable-operator/SKILL.md +1 -4
  70. package/skills/fastapi/SKILL.md +50 -82
  71. package/skills/flutter/SKILL.md +41 -89
  72. package/skills/go/SKILL.md +57 -105
  73. package/skills/harness/SKILL.md +52 -68
  74. package/skills/implement/SKILL.md +1 -1
  75. package/skills/init/SKILL.md +152 -168
  76. package/skills/marketing/SKILL.md +30 -80
  77. package/skills/nextjs/SKILL.md +42 -116
  78. package/skills/orient/SKILL.md +25 -20
  79. package/skills/parallel/SKILL.md +9 -75
  80. package/skills/plan/SKILL.md +92 -165
  81. package/skills/postgresdb/SKILL.md +52 -72
  82. package/skills/presentations/SKILL.md +49 -87
  83. package/skills/python/SKILL.md +23 -72
  84. package/skills/react/SKILL.md +19 -67
  85. package/skills/review/SKILL.md +22 -52
  86. package/skills/rust/SKILL.md +40 -115
  87. package/skills/sdd-init/SKILL.md +9 -14
  88. package/skills/secure-coding/SKILL.md +80 -109
  89. package/skills/ship/SKILL.md +25 -55
  90. package/skills/tasks/SKILL.md +37 -61
  91. package/skills/typescript/SKILL.md +22 -55
  92. package/skills/verify/SKILL.md +8 -32
  93. package/skills/viral-score/SKILL.md +122 -0
  94. package/skills/viral-score/evals/README.md +16 -0
  95. package/skills/viral-score/evals/cases.yaml +50 -0
  96. package/skills/vue-nuxt/SKILL.md +45 -106
  97. package/skills/worktrees/SKILL.md +24 -69
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: building-agents
3
- description: "Use when designing or building an LLM agent, tool-using system, RAG pipeline, eval harness, or MCP server in this repo — across any provider (OpenAI, Anthropic, Google Gemini, or OSS via OpenAI-compatible endpoints / litellm). Triggers: 'build an agent', 'add tool calling / function calling', 'structured JSON output', 'RAG / retrieval / embeddings / rerank', 'agent loop / ReAct / orchestrator-worker / multi-agent', 'LLM eval / golden set / LLM-as-judge / regression gate', 'prompt caching / model routing / token budget / cost control', 'trace / observability for LLM calls', 'build an MCP server', or 'make our LLM code provider-agnostic / swap models'. FastAPI/Python, Next.js, Go, Flutter, Postgres stacks."
3
+ description: "Use when building or restructuring an LLM agent — provider adapter, tool calling, structured output, RAG, agent loop, eval gate, cost routing, tracing, MCP server — model-agnostic across OpenAI/Anthropic/Gemini/OSS so a model swap is a config change. NOT vector-store SQL alone (that is `postgresdb`) or service deployment (that is `deployment`)."
4
4
  tags: [agents, llm, mcp, rag, evals, ai]
5
5
  recommends: [secure-coding, deployment]
6
6
  origin: risco
@@ -8,65 +8,26 @@ origin: risco
8
8
 
9
9
  # Building production LLM agents (model-agnostic)
10
10
 
11
- Build production LLM agents that are model-agnostic by construction — a thin provider adapter, a disciplined agent loop, schema-validated tools, provider-neutral RAG, eval gates, OTel tracing, and optionally an MCP server — so swapping OpenAI ↔ Anthropic ↔ Gemini ↔ OSS is a config change, not a rewrite.
11
+ A thin provider adapter, a disciplined agent loop, schema-validated tools, provider-neutral RAG, eval gates, OTel tracing, and optionally an MCP server — so swapping OpenAI ↔ Anthropic ↔ Gemini ↔ OSS is a config change, not a rewrite.
12
12
 
13
13
  ## The one rule
14
14
 
15
- > Program against a **capability interface**, never a vendor SDK. Vendor specifics (model id, tool-schema shape, JSON mode, caching, token limits) live behind one adapter resolved from config. If a model name or price appears in business logic, it's a bug.
15
+ > Program against a **capability interface**, never a vendor SDK. Vendor specifics (model id, tool-schema shape, JSON mode, caching, token limits) live behind one adapter resolved from config. Model names and prices rot — if one appears in business logic it's a bug, and re-verify the dated tables before quoting a number.
16
16
 
17
- > Model names and prices rot. Never hardcode them in app logic — resolve from config/registry, and re-verify the dated tables before quoting a number.
18
-
19
- ## When to use / When NOT to use
20
-
21
- > **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
22
-
23
- **Use when:** starting any production-bound LLM feature; code is hardwired to one SDK and you want to swap/route/fallback models; adding tools/function calling, structured output, or streaming; standing up RAG over Postgres/`pgvector` or an external store; building an eval harness / CI quality gate; adding tracing, cost tracking, caching, or routing/cascades; building or hardening an MCP server.
24
-
25
- **Do NOT use when:**
26
-
27
- - One-shot throwaway prompt, no tools, no eval, no production path → just call the SDK directly.
28
- - Pure prompt-wording improvement with no architecture → that's prompt engineering, not this.
29
- - Anthropic-SDK-specific tuning (caching internals, thinking, batch) in a file that *only* imports `anthropic` → defer to a dedicated Anthropic-SDK skill if your environment provides one (e.g. `claude-api`); this skill stays multi-provider.
30
- - Workspace scaffolding (`01-TOOLS`/`02-DOCS` layout) → **`harness`**.
31
- - Picking *which* coding agent (Claude Code vs Aider) → agent-eval territory, not this.
32
- - No retrieval, no tools, no loop, no evals at all → you don't need an agent; say so.
17
+ **Hand off instead when:** a new non-trivial feature has no approved spec + plan under `02-DOCS/wiki/sdd/` → stop and run [`specify`](../specify/SKILL.md) first (method: [`sdd`](../sdd/SKILL.md)), which routes back here once the plan is approved; one-line/low-risk changes go straight through. Anthropic-SDK internals (caching, thinking, batch) in a file that *only* imports `anthropic` → `claude-api` if your environment has it, since this skill stays multi-provider. Workspace scaffolding → [`harness`](../harness/SKILL.md). Choosing *which* coding agent to use → agent-eval territory. Pure prompt-wording tuning with no architecture change → prompt engineering, not this. A one-shot throwaway prompt, or no retrieval/tools/loop/evals at all → you don't need an agent; call the SDK directly and say so.
33
18
 
34
19
  ## Decision rules (read before writing code)
35
20
 
36
21
  1. **Adapter first** — define the `LLMProvider` Protocol before any provider call.
37
- 2. **Smallest loop that works** — single-agent before multi-agent; ReAct only when the path is uncertain; plan-execute when steps are knowable.
22
+ 2. **Smallest loop that works** — single-agent before multi-agent; ReAct only when the path is uncertain; plan-execute when steps are knowable. Multi-agent means orchestrator-worker with a semaphore-bounded parallel fan-out, never a free-for-all.
38
23
  3. **Tools are typed contracts** — schema + validation + idempotency key on every side-effecting tool; no catch-all tools.
39
24
  4. **Retrieve, don't stuff** — RAG when ground truth lives in data; cite or refuse.
40
25
  5. **Eval before ship** — a golden set + regression gate in CI, or it's not production.
41
26
  6. **Cheapest model that passes the eval** — route/cascade up, never default to flagship.
42
27
 
43
- ## Architecture at a glance
44
-
45
- ```text
46
- ┌───────────────────────────────────────────────────────────┐
47
- Caller ──▶│ Agent loop (perceive → decide → act → observe, bounded) │
48
- └───────────────────────────────────────────────────────────┘
49
- │ │ │ │
50
- ▼ ▼ ▼ ▼
51
- ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
52
- │ Provider │ │ Tool │ │ Retriever │ │ Tracer │
53
- │ adapter │ │ registry │ │ (pgvector) │ │ (OTel) │
54
- │ ↔ OpenAI / │ │ → sandboxed│ │ → cite/ │ │ gen_ai.* │
55
- │ Anthropic /│ │ tools │ │ refuse │ │ │
56
- │ Gemini /OSS│ └────────────┘ └────────────┘ └────────────┘
57
- └────────────┘
58
- ▲ │
59
- └──────────── Eval gate (CI) ◀─────────────┘
60
- provider-abstraction.md agent-loops…/tools-and-rag.md evals-and-observability.md
61
- ```
62
-
63
28
  ## The provider adapter (the heart of the skill)
64
29
 
65
- The one payload to internalize. Python 3.12+, Pydantic v2, **async** so it composes
66
- directly with the agent loop in `references/agent-loops-and-harness.md`. Streaming,
67
- the Gemini and OSS/litellm adapters, tool-result plumbing, and a `route()` registry live
68
- in `references/provider-abstraction.md` — this excerpt is the load-bearing core, not the
69
- whole interface.
30
+ The one payload to internalize. Python 3.12+, Pydantic v2, **async** so it composes directly with the bounded loop (and orchestrator-worker fan-out) in [`references/agent-loops-and-harness.md`](references/agent-loops-and-harness.md). Structured output is the quirk that differs most per vendor: strict JSON Schema (OpenAI), tool-forcing (Anthropic), `response_json_schema` (Gemini). Streaming, the Gemini and OSS/litellm adapters, tool-result plumbing, and a `route()` registry live in [`references/provider-abstraction.md`](references/provider-abstraction.md) — this excerpt is the load-bearing core, not the whole interface.
70
31
 
71
32
  ```python
72
33
  from __future__ import annotations
@@ -176,21 +137,7 @@ def get_provider(spec: str | None = None) -> LLMProvider:
176
137
 
177
138
  ## Good vs Bad
178
139
 
179
- ```python
180
- # BAD — vendor SDK + model id hardwired into a handler; swapping = rewrite every call-site.
181
- client = OpenAI()
182
- def summarize(text: str) -> str:
183
- r = client.chat.completions.create(model="gpt-5.5", messages=[{"role": "user", "content": text}])
184
- return r.choices[0].message.content
185
- ```
186
-
187
- ```python
188
- # GOOD — one adapter resolved from config; logic never names a model.
189
- provider = get_provider(settings.llm) # e.g. "anthropic:claude-sonnet-4-6"
190
- async def summarize(text: str) -> str:
191
- req = CompletionRequest(model=settings.model_id, messages=[Message(role="user", content=text)])
192
- return (await provider.complete(req)).text
193
- ```
140
+ Call-sites use the adapter and never name a model: `provider = get_provider(settings.llm)` (e.g. `"anthropic:claude-sonnet-4-6"`), then `await provider.complete(req)`. The two failures that survive that discipline:
194
141
 
195
142
  ```python
196
143
  # BAD — parse-and-pray; wrong shape fails silently at 3am.
@@ -276,9 +223,10 @@ def dispatch(name: str, raw_args: dict) -> ToolResult:
276
223
  return ToolResult(status="error", summary="invalid args", data={"errors": e.errors()},
277
224
  next_actions=["fix the arguments and retry"])
278
225
  return handler(args)
279
- # schema design, sandboxing, idempotency, DI-scoped DB sessions -> references/tools-and-rag.md
280
226
  ```
281
227
 
228
+ Schema design, sandboxing, idempotency, DI-scoped DB sessions, plus the RAG internals below — chunking, hybrid RRF, rerank, the citation grader, memory — are in [`references/tools-and-rag.md`](references/tools-and-rag.md).
229
+
282
230
  ## RAG in 30 lines (provider-agnostic embeddings)
283
231
 
284
232
  ```sql
@@ -320,7 +268,6 @@ async def answer(query: str) -> str:
320
268
  Message(role="user", content=f"{context}\n\nQ: {query}")],
321
269
  )
322
270
  return (await provider.complete(req)).text
323
- # chunking, hybrid RRF, rerank, citation grader, memory -> references/tools-and-rag.md
324
271
  ```
325
272
 
326
273
  ## Evals & cost gates (the production line)
@@ -355,8 +302,8 @@ async def run_eval(golden_path: str, graders: list, thresholds: dict[str, float]
355
302
  ```
356
303
 
357
304
  Routing cascade in one line: `route(task) → cheapest model whose eval passes; escalate only on a failed self-check`.
358
-
359
- Pointer: full runner, judge, CI gate, caching, batching, budgets → `references/evals-and-observability.md`.
305
+ Full runner, judge, CI gate, caching, batching and budgets →
306
+ [`references/evals-and-observability.md`](references/evals-and-observability.md).
360
307
 
361
308
  ## Observability (OTel GenAI, vendor-neutral)
362
309
 
@@ -381,10 +328,10 @@ async def traced_complete(provider: LLMProvider, req: CompletionRequest) -> Comp
381
328
 
382
329
  ## MCP: when and the smallest server
383
330
 
384
- **Native tools** when the agent and tools share a process/repo. **MCP** when tools must be reused across clients/teams or run out-of-process — accept the MCP cost (schema tokens, transport, ops) in exchange for reuse.
331
+ **Native tools** when the agent and tools share a process/repo. **MCP** when tools must be reused across clients/teams or run out-of-process — accept the MCP cost (schema tokens, transport, ops) in exchange for reuse. TypeScript server, transports, HTTP+auth and testing are in [`references/mcp-servers.md`](references/mcp-servers.md).
385
332
 
386
333
  ```python
387
- from fastmcp import FastMCP # standalone fastmcp 2.x; see references/mcp-servers.md
334
+ from fastmcp import FastMCP # standalone fastmcp 2.x
388
335
 
389
336
  mcp = FastMCP("invoices")
390
337
 
@@ -406,12 +353,11 @@ def read_invoice(invoice_id: str) -> str:
406
353
  if __name__ == "__main__":
407
354
  mcp.run() # stdio transport
408
355
  # (MCP spec 2025-11-25; stateless-core RC 2026-07-28; verify before quoting)
409
- # TypeScript server, transports, HTTP+auth, testing -> references/mcp-servers.md
410
356
  ```
411
357
 
412
- ## Anti-patterns → STOP
358
+ ## Anti-patterns
413
359
 
414
- | Rationalization | Reality |
360
+ | Anti-pattern | Reality |
415
361
  |---|---|
416
362
  | "I'll just call the OpenAI SDK directly, we'll never switch" | The adapter is ~40 lines; retrofitting it across 30 call-sites later is a rewrite. Adapter first. |
417
363
  | "JSON output is usually valid, I'll parse it" | "Usually" = pages at 3am. Use strict structured output + schema validation. |
@@ -426,44 +372,15 @@ if __name__ == "__main__":
426
372
  | "Tool results just return the raw API blob" | Give the model `status/summary/next_actions`; raw blobs waste context and stall recovery. |
427
373
  | "Prompt caching is Anthropic-only so skip caching" | Each provider has its own caching/dedup; abstract it behind the adapter, don't skip it. |
428
374
 
429
- ## Quick reference
430
-
431
- | Task | Do this | Reference |
432
- |---|---|---|
433
- | Define a provider | `LLMProvider` Protocol + normalized request/response | `references/provider-abstraction.md` |
434
- | Add a tool | Pydantic args model + `ToolResult` + validating dispatcher | `references/tools-and-rag.md` |
435
- | Structured output | Strict JSON Schema (OpenAI) / tool-forcing (Anthropic) / `response_json_schema` (Gemini) | `references/provider-abstraction.md` |
436
- | Build the loop | Bounded perceive → decide → act → observe with budgets | `references/agent-loops-and-harness.md` |
437
- | Multi-agent | Orchestrator-worker + parallel fan-out with a semaphore | `references/agent-loops-and-harness.md` |
438
- | RAG | `pgvector` ANN + hybrid RRF + rerank + cite | `references/tools-and-rag.md` |
439
- | Eval gate | Golden set + graders + CI threshold exit code | `references/evals-and-observability.md` |
440
- | Trace | OTel GenAI `gen_ai.*` spans, swappable exporter | `references/evals-and-observability.md` |
441
- | Cut cost | Cache + route/cascade + batch + budgets | `references/evals-and-observability.md` |
442
- | MCP server | FastMCP stdio / Streamable HTTP server | `references/mcp-servers.md` |
443
-
444
375
  ## verify.sh
445
376
 
446
377
  `scripts/verify.sh` lints example agent code and dry-runs the eval smoke test in **the user's project** — not in this skill repo. It detects each tool (`ruff`, `mypy`, `tsc`/`node`, `go`, the eval entrypoint, `markdownlint`) and skips any that are missing with a yellow WARN; a missing tool never fails the run. Invoke it with `bash scripts/verify.sh` from the project root. Exit 0 means clean (or only skips); a non-zero exit means a real lint/typecheck/vet/eval failure.
447
378
 
448
- ## Project grounding (02-DOCS + CLAUDE.md)
449
-
450
- When this skill runs in a project with a `02-DOCS/` layer (the
451
- [`harness`](../harness/SKILL.md) Karpathy wiki), record this
452
- project's agent decisions there and index them in `02-DOCS/wiki/index.md`, so the next
453
- agent inherits the conventions instead of re-deriving them.
454
-
455
- 1. **Find the article** `02-DOCS/wiki/stack/agents.md`, indexed in `02-DOCS/wiki/index.md` (the Knowledge map index; root `CLAUDE.md` points to it).
456
- 2. **If missing or stale**, create/update it with the project's real choices — the provider(s) and model routing, where the provider adapter lives, tool/RAG conventions, the eval gates, and the observability backend —
457
- then index it in `02-DOCS/wiki/index.md` (the Knowledge map; root `CLAUDE.md` keeps only a short pointer to it). Write it as an OKF v0.1 wiki article per the harness [`wiki-article-template.md`](../harness/references/wiki-article-template.md): open with YAML frontmatter carrying a non-empty `type:` (use `type: stack`), and use standard markdown links — never wikilinks.
458
- 3. **Read it first on every use** and stay consistent; when a convention changes, update the
459
- article (bump its `timestamp`) in the same change.
379
+ ## Project grounding
460
380
 
461
- No `02-DOCS/` layer? Skip silently (optionally suggest `harness`). Unlike the
462
- brand study, technical conventions are *recorded, not gated* — never block the task on this.
381
+ In a project with a `02-DOCS/` layer ([`harness`](../harness/SKILL.md)), read `02-DOCS/wiki/stack/agents.md` first on every use and stay consistent with it. If it is missing or stale, write this project's real choices there — provider(s) and model routing, where the adapter lives, tool/RAG conventions, eval gates, observability backend — as a `type: stack` article per the harness [`wiki-article-template.md`](../harness/references/wiki-article-template.md), index it in `02-DOCS/wiki/index.md`, and bump its `timestamp` in the same change as any convention change. No `02-DOCS/`? Skip silently — technical conventions here are *recorded, not gated*; never block the task on this.
463
382
 
464
- ## See Also
383
+ ## See also
465
384
 
466
- - `../harness/SKILL.md` — workspace `01-TOOLS`/`02-DOCS` scaffolding.
467
- - Stack siblings the examples target: `../fastapi/SKILL.md`, `../nextjs/SKILL.md`, `../go/SKILL.md`, `../postgresdb/SKILL.md`, `../flutter/SKILL.md`; plus `../secure-coding/SKILL.md` and `../deployment/SKILL.md` for hardening and shipping the agent service.
468
- - External skills (no sibling in this repo; use if your environment provides them): `claude-api` — Anthropic-SDK-specific tuning (caching internals, thinking, batch) when a file only imports `anthropic`; `deep-research` — the research-harness fan-out / verify pattern.
469
- - ECC analogues (external, no links): `agent-harness-construction`, `eval-harness`, `cost-aware-llm-pipeline`, `mcp-server-patterns`, `context-budget`.
385
+ - Stacks the examples target: [`fastapi`](../fastapi/SKILL.md), [`nextjs`](../nextjs/SKILL.md), [`go`](../go/SKILL.md), [`postgresdb`](../postgresdb/SKILL.md), [`flutter`](../flutter/SKILL.md). Harden with [`secure-coding`](../secure-coding/SKILL.md), ship with [`deployment`](../deployment/SKILL.md).
386
+ - External (no sibling here; use if your environment provides them): `claude-api` for Anthropic-SDK-only tuning, `deep-research` for the research-harness fan-out / verify pattern.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: business-intelligence
3
- description: "Use when someone wants to ask business questions over the org's data in plain language and get consistent, trustworthy numbers, when a metric (revenue, MRR, active users, gross margin) must be defined once so every dashboard/report/agent computes it identically, when wiring an LLM or agent to query data without hallucinating SQL, or when two teams report different numbers for the same thing. Triggers: 'semantic layer', 'metrics layer', 'define MRR once', 'self-serve analytics in plain English', 'text-to-SQL but trustworthy', 'sales and finance disagree on revenue', 'the agent keeps hallucinating SQL', 'dbt Semantic Layer', 'MetricFlow', 'Cube', 'capa semántica', 'consultar dades en llenguatge natural'. NOT designing chart layout or panels (that is dashboard), NOT choosing which KPIs to track (that is kpi-framework), NOT writing the raw query by hand (that is sql)."
3
+ description: "Use when a metric (revenue, MRR, margin) needs defining once in a governed semantic layer so every dashboard, report and agent returns the same number, or when an LLM must answer data questions in plain language without hallucinating SQL. NOT chart layout (that is `dashboard`), NOT which KPIs to track (that is `kpi-framework`), NOT a hand-written query (that is `sql`)."
4
4
  tags: [business-intelligence, semantic-layer, metrics-layer, text-to-sql, natural-language-query, dbt, cube]
5
5
  recommends: [sql, dashboard, kpi-framework, reporting, analytics, forecasting, clickhouse-analytics, duckdb]
6
6
  origin: risco
@@ -119,15 +119,6 @@ Question: "MRR by plan, monthly, last 2 quarters, EU customers only"
119
119
  filter -> region = 'EU'
120
120
  ```
121
121
 
122
- ```text
123
- Pregunta (ES/CA): "ingresos por región, mensual, últimos 2 trimestres, solo UE"
124
- metric -> gross_revenue
125
- group by -> region
126
- time grain -> month
127
- date filter -> last 2 quarters
128
- filter -> region = 'EU'
129
- ```
130
-
131
122
  You hand the layer that spec; it generates the governed SQL. You then explain the answer back in business terms ("EU MRR grew 8% QoQ, driven by the Pro plan"), not as a table dump.
132
123
 
133
124
  ## Wire the agent
@@ -155,22 +146,17 @@ Author toward the **Open Semantic Interchange** standard so definitions survive
155
146
 
156
147
  ## Anti-patterns
157
148
 
158
- | Rationalization | Reality | STOP |
149
+ | Anti-pattern | Why it bites | Instead |
159
150
  |---|---|---|
160
- | "Just free-hand the SQL this once, it's faster" | "Once" becomes the fourth conflicting revenue figure; it's unauditable | Add/query a metric |
161
- | "Each dashboard can define revenue itself" | That is exactly how you get three numbers and a fire drill | One metric, all consumers query it |
162
- | "The time dimension grain is obvious, skip declaring it" | Undeclared grain → silent daily-vs-monthly mismatches | Declare `time_granularity`/`grain` |
163
- | "Give the agent warehouse creds, it'll figure out the joins" | Raw text-to-SQL is 84-90% (33% in 2023); unauditable | Expose metrics via MCP/API |
164
- | "Stand up a semantic layer for this 200-row CSV" | Pure overhead for one analyst | `../sql/SKILL.md` / `../duckdb/SKILL.md` |
165
- | "The LLM is smart enough to write correct SQL" | The dbt 2026 benchmark says the layer is +8-14pts more accurate | Ground it in the layer |
166
- | "Hard-code the EU filter into the metric" | Now you need a second metric for every region | Pass filters at query time |
151
+ | Free-handing the SQL "just this once" because it's faster | "Once" becomes the fourth conflicting revenue figure; it's unauditable | Add/query a metric |
152
+ | Letting each dashboard define revenue itself | That is exactly how you get three numbers and a fire drill | One metric, all consumers query it |
153
+ | Skipping the time dimension's grain because it's "obvious" | Undeclared grain → silent daily-vs-monthly mismatches | Declare `time_granularity`/`grain` |
154
+ | Handing the agent warehouse creds to figure out the joins | Raw text-to-SQL is 84-90% (33% in 2023) and unauditable; the dbt 2026 benchmark puts the layer +8-14pts ahead | Expose metrics via MCP/API |
155
+ | Standing up a semantic layer for a 200-row CSV | Pure overhead for one analyst | `../sql/SKILL.md` / `../duckdb/SKILL.md` |
156
+ | Hard-coding the EU filter into the metric | Now you need a second metric for every region | Pass filters at query time |
167
157
 
168
158
  ## Verify
169
159
 
170
160
  Run `scripts/verify.sh [path]` on your semantic-model directory. It is read-only, never touches a warehouse, and discovers candidate YAML, then warns (advisory) on: a metric with no underlying measure, a measure with no declared `agg`, a time dimension with no grain, duplicate metric names, and a `.sql` beside the model hand-rolling an aggregate the layer should own. It exits non-zero only on unparseable YAML; an empty or clean target passes clean.
171
161
 
172
- ## See also
173
-
174
- - `references/authoring-semantic-models.md` — multi-entity models, metric types, semi-additive measures, time spines, fan-out traps.
175
- - `references/wiring-agents-and-apis.md` — MCP metrics-tool pattern, dbt SL / Cube query shapes, agent guardrails.
176
- - Siblings: `../sql/SKILL.md` · `../dashboard/SKILL.md` · `../kpi-framework/SKILL.md` · `../reporting/SKILL.md` · `../analytics/SKILL.md` · `../forecasting/SKILL.md`
162
+ Siblings: `../sql/SKILL.md` · `../dashboard/SKILL.md` · `../kpi-framework/SKILL.md` · `../reporting/SKILL.md` · `../analytics/SKILL.md` · `../forecasting/SKILL.md`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: calendar-scheduling
3
- description: "Use when adding booking/scheduling to a product — a 'pick a slot' page, an embedded Cal.com/Calendly widget, or a flow that shows real availability and writes the confirmed meeting to Google/Outlook/Apple — and when fixing the three classic bugs: double-booking, wrong-time-after-DST, and orphaned events on reschedule. Triggers: 'add a book-a-call page', 'embed Cal.com and white-label it', 'show my real availability and create the calendar event', 'we keep getting double-booked when two people pick the same slot', 'bookings show the wrong time after the clocks changed', 'fire a webhook on each booking', 'añade reservas de citas a la web y evita solapamientos con mi calendario de Outlook', 'evita que se reserve dos veces el mismo hueco'. NOT raw calendar CRUD, free/busy plumbing, or watch channels for an internal app with no booking surface (that is google-workspace), NOT a generic non-booking inbound event receiver (that is webhooks), NOT charging for a paid appointment (that is stripe)."
3
+ description: "Use when a product needs a booking surface — a pick-a-slot page, a Cal.com/Calendly embed, or real availability plus the confirmed meeting written to Google/Outlook — or when fixing double-booking, DST drift, or orphaned reschedule events. NOT calendar CRUD with no booking surface (that is `google-workspace`), NOT the payment (that is `stripe`)."
4
4
  tags: [scheduling, booking, calendar, calcom, calendly, google-calendar, availability, webhooks]
5
5
  recommends: [google-workspace, webhooks, automation-flows, email-connector, stripe, sales-pipeline]
6
6
  profiles: []
@@ -12,17 +12,9 @@ origin: risco
12
12
  Scheduling is always two halves bolted together: a **booking surface** (an
13
13
  external person reserves a slot — embed, atom, or API call) and **calendar
14
14
  sync** (you read free/busy to compute availability and write the confirmed
15
- event back). Ship one without the other and you get the three bugs this skill
16
- exists to prevent:
17
-
18
- - **Double-booking** — two people grab the same slot because availability was
19
- computed in the browser or written before a re-check.
20
- - **Timezone drift** — a meeting shows the wrong hour after a DST change because
21
- a wall-clock time was stored instead of an instant + IANA zone.
22
- - **Orphaned events** — a reschedule creates a *second* calendar event instead
23
- of moving the first, so the calendar fills with phantoms.
24
-
25
- Everything below is in service of not shipping those.
15
+ event back). Ship one without the other and you get the three bugs the rest of
16
+ this skill exists to prevent: **double-booking**, **timezone drift** after a DST
17
+ change, and **orphaned events** on reschedule.
26
18
 
27
19
  ## Decide the altitude first
28
20
 
@@ -38,7 +30,9 @@ Pick the lowest-code option that still owns the data model you actually need.
38
30
  Why per row: the embed is zero-maintenance but a black box; the atom/API buys
39
31
  your own UI without owning sync; raw provider is full control and full
40
32
  liability; a unified API trades a vendor for not maintaining three calendar
41
- integrations. Full comparison in `references/provider-matrix.md`.
33
+ integrations. Hosting, auth/scopes, webhook events, cross-domain support and
34
+ when each wins, per provider:
35
+ [`references/provider-matrix.md`](references/provider-matrix.md).
42
36
 
43
37
  - **Cal.com** is open-source and self-hostable. Self-hosted instances get
44
38
  **unlimited API access** (no cloud rate limit) and full white-label by
@@ -78,9 +72,6 @@ Scope ladder, narrowest first:
78
72
  - `calendar` / `calendar.events` — restricted; request only if you genuinely
79
73
  manage arbitrary events the app didn't create.
80
74
 
81
- **Calendly:** OAuth 2.1 or a personal access token. **Cal.com self-host:** no
82
- rate-limit anxiety, so no token-bucket gymnastics needed in your client.
83
-
84
75
  ## Availability without double-booking — the core flow
85
76
 
86
77
  Both classic races (computing slots in the browser, and writing the event
@@ -107,8 +98,10 @@ Decision — do you need a hold step?
107
98
  | Multi-step booking form, payment, or high contention | Yes — a TTL lock so the slot survives the form and releases if abandoned |
108
99
 
109
100
  Google's availability primitive is `freebusy.query` (POST, returns busy blocks
110
- per calendar); the write is `events.insert`. Payloads in
111
- `references/google-calendar-sync.md`.
101
+ per calendar); the write is `events.insert`. Both payloads (with
102
+ `conferenceData` for Meet), `watch` channels + sync tokens, recurring-event edge
103
+ cases and refresh-token handling:
104
+ [`references/google-calendar-sync.md`](references/google-calendar-sync.md).
112
105
 
113
106
  ## Timezone correctness
114
107
 
@@ -180,15 +173,6 @@ that orchestration is **automation-flows**, not here.
180
173
  | Poll the calendar for changes | Slow, rate-limited, misses edits | `watch` push channels + incremental sync tokens |
181
174
  | Write new code against Calendly v1 | v1 API + webhooks dead since May 2025 | Calendly v2 (OAuth 2.1 / PAT) |
182
175
 
183
- ## References
184
-
185
- - `references/provider-matrix.md` — Cal.com vs Calendly vs Google direct vs
186
- Nylas v3 vs Cronofy: hosting, auth/scopes, webhook events, cross-domain,
187
- when each wins.
188
- - `references/google-calendar-sync.md` — `freebusy.query` and `events.insert`
189
- (with `conferenceData` for Meet) payloads, `watch` channels + sync tokens,
190
- recurring-event edge cases, refresh-token handling.
191
-
192
176
  Adjacent skills: raw calendar CRUD / watch channels with no booking →
193
177
  [`../google-workspace/SKILL.md`](../google-workspace/SKILL.md); charging for a
194
178
  paid appointment → [`../stripe/SKILL.md`](../stripe/SKILL.md); booking funnel as
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: case-studies
3
- description: "Use when turning a real customer win into a case study or testimonial — a metrics-anchored success story or an attributed quote a prospect can act on, including when a great result reads like a brochure and needs to convert. Triggers: 'turn this customer win into a case study', 'we cut their churn 40% — write it up', 'draft a testimonial quote from this customer-interview transcript', 'we have a 40% drop but the write-up sounds like marketing fluff — make it convert', 'build a reusable customer-story template plus an intake/consent form', 'escríbeme un caso de éxito de este cliente con métricas y una cita', 'redacta un cas d'èxit amb mètriques'. NOT the deck that pitches the vision to a room (that is pitch-deck), NOT a long thought-leadership article with no single named customer (that is article-writing)."
3
+ description: "Use when turning one named customer's measured win into a case study, or the attributed testimonial quote that travels with it — consent-cleared, metrics-anchored proof for the next skeptical buyer. NOT the deck that sells the vision to a room (that is `pitch-deck`), NOT thought-leadership with no single named customer (that is `article-writing`)."
4
4
  tags: [case-study, testimonial, social-proof, customer-story, conversion]
5
5
  recommends: [pitch-deck, article-writing, retention, review-management, brand-voice, landing-copy]
6
6
  origin: risco
@@ -29,7 +29,7 @@ If the request is not a single customer's measured outcome, hand it off before y
29
29
  | Drop the proven quote into a converting page | `../landing-copy/SKILL.md` |
30
30
  | Price the offer this win justifies | `pricing` |
31
31
 
32
- The one-sentence call: it is a case study if a real, named customer already got a measured result and consented to be quoted. Vision-to-a-room is `pitch-deck`; no-single-customer is `article-writing`.
32
+ The one-sentence call: it is a case study if a real, named customer already got a measured result and consented to be quoted.
33
33
 
34
34
  ## The intake gate — STOP if any of these is missing
35
35
 
@@ -61,7 +61,7 @@ quote_source: "interview-2026-05-20.txt"
61
61
  ---
62
62
  ```
63
63
 
64
- `consent: pending` means draft-only. `consent: anonymized` means no name/logo/identifying detail ships. Only `consent: signed` may publish a named, quoted, imaged customer. Full intake form, approval-email wording, and substantiation notes live in `references/consent-and-substantiation.md`.
64
+ `consent: pending` means draft-only. `consent: anonymized` means no name/logo/identifying detail ships. Only `consent: signed` may publish a named, quoted, imaged customer. Full intake form, consent/release checklist, approval-email wording, substantiation and insider-disclosure notes, and the anonymization fallback rules live in `references/consent-and-substantiation.md`.
65
65
 
66
66
  ## Case-study anatomy
67
67
 
@@ -140,8 +140,3 @@ Write the prose so these fall out cleanly; do not produce a separate brochure fo
140
140
  `scripts/verify.sh <case-study.md>` is a read-only structural and legal lint. It checks for a quantified hero metric, the required Challenge/Solution/Result sections and snapshot box, an attributed quote, a before→after signal, a CTA, and the `consent:` / `approved:` marker — and it warns on the superlative banlist. It **fails hard** when the hero has no metric, a core section is missing, or consent is unmarked, because shipping an un-consented named quote is the legal risk. It is structural lint only; persuasion quality is the capability eval's job and yours.
141
141
 
142
142
  Hand off when the piece is done: the proven quote → `../landing-copy/SKILL.md`, the broader narrative → `../article-writing/SKILL.md`, the slide version → `../pitch-deck/SKILL.md`, the public-review angle → `../review-management/SKILL.md`.
143
-
144
- ## References
145
-
146
- - `references/case-study-skeleton.md` — the full ordered template (results headline, snapshot box, C-S-R sections with Context-Achievement-Relevance metric lines, attributed quote block, CTA) plus a filled mini-example with consent front-matter.
147
- - `references/consent-and-substantiation.md` — intake-form fields, consent/release checklist, exact-quote-approval email wording, FTC substantiation and insider-disclosure notes, anonymization fallback rules.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: chatbot
3
- description: "Use when putting a support or sales bot on a live website and it must behave — writing or hardening its persona/system prompt, designing the bot→human handoff, stopping it inventing prices/policies/refunds, defending against jailbreaks and prompt injection, qualifying leads, or setting launch metrics and a kill switch. Triggers: 'put a chatbot on our site that answers from our docs', 'add a chat widget', 'our bot promised a refund we don't offer — lock it down', 'stop people jailbreaking our website assistant', 'design the handoff to a human agent', 'qualify leads and book demos', 'necesito un chatbot de ventas para la web que califique leads i reservi demos'. NOT building the agent loop/RAG index/eval harness under it (that is building-agents), and NOT a human answering one live ticket (that is customer-support)."
3
+ description: "Use when a support or sales bot on a live website must behave: persona/system prompt, grounding so it cannot invent prices or policy, jailbreak and injection defense, the human handoff, launch metrics and kill switch. NOT the agent loop or RAG index under it (that is `building-agents`), NOT a human answering one ticket (that is `customer-support`)."
4
4
  tags: [chatbot, support-bot, sales-bot, handoff, guardrails, grounding, conversational-ai]
5
5
  recommends: [building-agents, rag, customer-support, agent-safety, prompt-engineering, brand-voice]
6
6
  origin: risco
@@ -10,26 +10,14 @@ origin: risco
10
10
 
11
11
  This skill owns the bot that sits on a public site 24/7, answers support or sales questions, deflects what it safely can, and hands off cleanly what it can't. Four parts and nothing else: its **persona** (system prompt), its **grounding** (what it's allowed to know), its **guardrails** (what it must never say or do), and its **handoff** (when and how it gives up to a human). The retrieval engine under it is [`../building-agents/SKILL.md`](../building-agents/SKILL.md); the human who picks up the escalation is [`../customer-support/SKILL.md`](../customer-support/SKILL.md). You are productizing a bot, not engineering an agent and not working a ticket.
12
12
 
13
+ Not here: the agent loop, tool schemas and eval harness → [`../building-agents/SKILL.md`](../building-agents/SKILL.md) (and `rag` for the index half: chunking, embeddings, rerank); one live ticket answered by a human — triage, SLA, macros → [`../customer-support/SKILL.md`](../customer-support/SKILL.md); prompt *wording* in the abstract → `prompt-engineering`; general LLM abuse taxonomy beyond the public-bot case → `agent-safety`; the golden-set eval as an engineering artifact → `agent-eval`; win-back/renewal → [`../retention/SKILL.md`](../retention/SKILL.md); new-customer welcome → [`../client-onboarding/SKILL.md`](../client-onboarding/SKILL.md); generic automation wiring → [`../automation-flows/SKILL.md`](../automation-flows/SKILL.md); WhatsApp/Telegram channel plumbing → [`../whatsapp-telegram/SKILL.md`](../whatsapp-telegram/SKILL.md).
14
+
13
15
  ## The one rule
14
16
 
15
17
  > The bot may state only what it can **cite** (from approved KB) or **confirm** (a fact it was given). Everything else is "Let me connect you to a human." Grounded-or-handoff. It never improvises a price, a policy, a refund, or a promise.
16
18
 
17
19
  Why: a hallucinated answer is a binding answer. Air Canada's bot invented a bereavement-refund policy; a tribunal held the airline liable for what the bot said (multiple 2025 retrospectives, accessed 2026-06-02). The bot speaks for the company in court, so cap what it's allowed to invent at zero.
18
20
 
19
- ## When to use / When NOT to use
20
-
21
- **Use when:** standing up a support/sales chat widget on a website; writing or hardening the bot's system prompt (scope, refusals, tone); designing escalation to a human and what context travels; stopping the bot inventing policy/price (incident hardening); defending against jailbreaks / prompt injection on a public bot; building a sales bot that qualifies a lead and books a demo; defining launch metrics (deflection/containment/handoff) and the threshold that pulls it back.
22
-
23
- **Do NOT use when:**
24
-
25
- - Building the agent loop, tool schemas, RAG pipeline, or eval harness under the bot → [`../building-agents/SKILL.md`](../building-agents/SKILL.md) (and `rag` for the index half: chunking, embeddings, rerank).
26
- - A human (or assisted) agent answering one live ticket — triage, SLA, macros → [`../customer-support/SKILL.md`](../customer-support/SKILL.md).
27
- - Improving prompt *wording* in the abstract, prompt-pattern library → `prompt-engineering`.
28
- - General LLM abuse taxonomy / red-team policy beyond the public-bot case → `agent-safety`.
29
- - Building the golden-set eval as an engineering artifact → `agent-eval`.
30
- - Win-back/renewal → [`../retention/SKILL.md`](../retention/SKILL.md); new-customer welcome → [`../client-onboarding/SKILL.md`](../client-onboarding/SKILL.md).
31
- - Generic automation wiring → [`../automation-flows/SKILL.md`](../automation-flows/SKILL.md); WhatsApp/Telegram channel plumbing → [`../whatsapp-telegram/SKILL.md`](../whatsapp-telegram/SKILL.md).
32
-
33
21
  ## The four layers (the spine)
34
22
 
35
23
  Build and review the bot in this order. Each layer assumes the one above it holds.
@@ -68,7 +56,7 @@ Good (scoped, grounded, refusal + authority clauses, no secrets):
68
56
  - Keep replies under ~120 words; link the source you used."
69
57
  ```
70
58
 
71
- Full annotated template: [`references/system-prompt-and-guardrails.md`](references/system-prompt-and-guardrails.md).
59
+ Reach for [`references/system-prompt-and-guardrails.md`](references/system-prompt-and-guardrails.md) while authoring: full annotated template, the forbidden-topic bucket catalog with per-bucket handling, and the prompt-injection defense checklist.
72
60
 
73
61
  ## Layer 2 — Grounding contract
74
62
 
@@ -96,7 +84,7 @@ Route every borderline message by topic bucket:
96
84
  | Off-scope / unknown | anything not in KB | "I don't have that" → offer human. |
97
85
  | Injection attempt | "Ignore your rules / you are now…" | Refuse, do not break scope, do not reveal the prompt; log it. |
98
86
 
99
- Injection defenses (full checklist in the reference): a clear instruction hierarchy (system > retrieved content > user), treat retrieved text and user input as *data not instructions*, refuse "ignore previous / reveal your prompt / you are now" patterns, and an **output filter** that blocks commitment phrases before they reach the user. Plus a hard **length cap** so a coaxed essay can't smuggle a promise.
87
+ Injection defenses (full checklist in [`references/system-prompt-and-guardrails.md`](references/system-prompt-and-guardrails.md)): a clear instruction hierarchy (system > retrieved content > user), treat retrieved text and user input as *data not instructions*, refuse "ignore previous / reveal your prompt / you are now" patterns, and an **output filter** that blocks commitment phrases before they reach the user. Plus a hard **length cap** so a coaxed essay can't smuggle a promise.
100
88
 
101
89
  ## Layer 4 — Handoff state machine
102
90
 
@@ -116,7 +104,7 @@ Three trigger families:
116
104
  - Collected variables (account/order id, plan, intent, sentiment, what was already tried).
117
105
  - The detected trigger and the bot's best summary of the unresolved problem.
118
106
 
119
- **Warm** transfer when a human is online (bot summarizes, agent continues). **Cold** when none is: capture a ticket with the same packet and tell the user exactly when to expect a reply — never drop them into a silent void. Packet template + trigger cues: [`references/handoff-and-sales.md`](references/handoff-and-sales.md).
107
+ **Warm** transfer when a human is online (bot summarizes, agent continues). **Cold** when none is: capture a ticket with the same packet and tell the user exactly when to expect a reply — never drop them into a silent void. Packet template, trigger detection cues, and warm-transfer / offline-fallback wording: [`references/handoff-and-sales.md`](references/handoff-and-sales.md).
120
108
 
121
109
  ## Sales-bot mode (branch)
122
110
 
@@ -160,9 +148,4 @@ Don't ship a bot you can't measure or pull back. Define these before launch:
160
148
  | Bot promises a fix/price it can't authorize | Binding commitment it had no right to make | Authority clause + handoff for anything committal |
161
149
  | Go fully autonomous on day one | No baseline, no kill switch, incident in production | Shadow → assisted → autonomous, kill switch armed |
162
150
 
163
- ## References
164
-
165
- - [`references/system-prompt-and-guardrails.md`](references/system-prompt-and-guardrails.md) — full annotated support-bot system prompt template, the forbidden-topic bucket catalog with per-bucket handling, and the prompt-injection defense checklist. Reach for it while authoring the prompt.
166
- - [`references/handoff-and-sales.md`](references/handoff-and-sales.md) — the handoff packet template, the explicit/implicit/topic trigger catalog with detection cues, warm-transfer and offline-fallback wording, and the sales qualification + demo-booking flow.
167
-
168
151
  Verify a candidate system prompt before shipping: `scripts/verify.sh path/to/system-prompt.md` (read-only structural + banlist linter; see `evals/README.md`).
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: chrome-extension
3
- description: "Use when building, structuring, or shipping a Manifest V3 browser extension and hitting its quirks — the service worker keeps dying or losing state between events, permission warnings scare users away, the Chrome Web Store rejected the listing, or you must drag an old Manifest V2 extension to V3. Triggers: 'build a Chrome extension', 'my background script keeps resetting its state', 'store rejected me for excessive permissions', 'migrate MV2 to MV3', 'content script messaging to the popup', 'declarativeNetRequest ad blocker', 'crear una extensión de Chrome', 'publicar a la Chrome Web Store', 'el service worker se muere'. NOT a generic web app (that is nextjs)."
3
+ description: "Use when building or shipping a Manifest V3 browser extension and hitting its quirks — service worker dying and losing state, permission warnings, a Chrome Web Store rejection, content-script/worker/popup messaging, or an MV2-to-V3 migration. NOT a generic web app (that is `nextjs`), NOT a desktop shell (that is `electron`)."
4
4
  tags: [chrome-extension, manifest-v3, browser-extension, service-worker, chrome-web-store]
5
5
  recommends: [nextjs, react, gdpr-privacy, secure-coding, vercel]
6
6
  origin: risco
@@ -134,7 +134,7 @@ chrome.action.onClicked.addListener(async (tab) => {
134
134
 
135
135
  - `run_at`: `document_start` (before DOM), `document_end`, or `document_idle` (default, after load). Pick `document_start` only if you must beat the page's own scripts.
136
136
  - **Isolated world** (default): your content script's JS is sandboxed from the page's JS — they share the DOM but not variables. Use **MAIN world** (`"world": "MAIN"`) only when you must touch the page's own JS objects, and know it loses the isolation guarantee.
137
- - For dynamic, user-supplied injection, `chrome.userScripts.execute()` exists (Chrome 135, Mar 2025) — see references.
137
+ - For dynamic, user-supplied injection, `chrome.userScripts.execute()` exists (Chrome 135, Mar 2025) — see [references/store-and-migration.md](references/store-and-migration.md).
138
138
 
139
139
  ## Storage, alarms, no remote code
140
140