@ericrisco/rsc 0.1.55 → 0.1.57
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 +16 -16
- package/package.json +1 -1
- package/skills/github-actions/SKILL.md +15 -27
- package/skills/linkedin-outreach/SKILL.md +11 -31
- package/skills/market-research/SKILL.md +13 -22
- package/skills/market-research/evals/cases.yaml +3 -3
- package/skills/meeting-notes/SKILL.md +15 -30
- package/skills/nestjs/SKILL.md +2 -10
- package/skills/nodejs/SKILL.md +13 -26
- package/skills/power-automate/SKILL.md +10 -19
- package/skills/prisma-orm/SKILL.md +3 -10
- package/skills/prisma-orm/evals/cases.yaml +2 -2
- package/skills/procurement/SKILL.md +1 -6
- package/skills/procurement/evals/cases.yaml +2 -2
- package/skills/react-native/SKILL.md +4 -14
- package/skills/react-native/scripts/verify.sh +5 -2
- package/skills/reporting/SKILL.md +21 -23
- package/skills/roast-me/SKILL.md +3 -5
- package/skills/roast-me/evals/cases.yaml +3 -3
- package/skills/ruby/SKILL.md +10 -31
- package/skills/shortform-ideation/SKILL.md +12 -20
- package/skills/shortform-strategy/SKILL.md +7 -19
package/skills/nestjs/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: nestjs
|
|
3
|
-
description: "Use when building or structuring a NestJS backend — feature modules, providers
|
|
3
|
+
description: "Use when building or structuring a NestJS backend — feature modules, providers and DI wiring, provider scopes and request-lifecycle order, where to bind guards/pipes/interceptors/filters, and testing with Test.createTestingModule. NOT a bare Express/Fastify service with no DI (that is `nodejs`), NOT framework-agnostic REST design (that is `api-design`)."
|
|
4
4
|
tags: [nestjs, nodejs, backend, dependency-injection, guards, pipes, testing, typescript]
|
|
5
5
|
recommends: [nodejs, typescript, api-design, prisma-orm, testing-web]
|
|
6
6
|
origin: risco
|
|
@@ -10,15 +10,7 @@ origin: risco
|
|
|
10
10
|
|
|
11
11
|
Build server-side Node apps the way NestJS intends: feature modules, providers wired through the DI container, controllers, and a cross-cutting layer bound at a deliberate scope. This skill is about Nest-specific mechanics — how DI scopes resolve, what order the request lifecycle runs in, where to bind guards/pipes/interceptors/filters, and how to test it with `Test.createTestingModule`.
|
|
12
12
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
- Scaffolding or extending a Nest app: new module, controller, provider, resolver.
|
|
16
|
-
- Wiring DI: `useClass` / `useValue` / `useFactory` / `useExisting`, injection tokens, `forwardRef`, dynamic modules (`forRoot` / `forRootAsync`).
|
|
17
|
-
- Adding cross-cutting behavior and deciding global vs controller vs route binding.
|
|
18
|
-
- "Why is my request-scoped provider undefined" / "circular dependency detected at bootstrap".
|
|
19
|
-
- Unit tests with mock providers and e2e tests with Supertest against the real Nest app.
|
|
20
|
-
|
|
21
|
-
## Not this when
|
|
13
|
+
## Not this — route instead
|
|
22
14
|
|
|
23
15
|
- Bare Express/Fastify/`http` service, no `@Module`/`@Injectable` → `../nodejs/SKILL.md`. Nest starts the moment the DI container appears.
|
|
24
16
|
- REST resource modeling, versioning, status codes, idempotency (framework-agnostic) → `../api-design/SKILL.md`. Nest is where you *implement* those decisions.
|
package/skills/nodejs/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: nodejs
|
|
3
|
-
description: "Use when building or
|
|
3
|
+
description: "Use when building or operating a plain Node.js / Express 5 backend service: project layout, async correctness, central error middleware, fail-fast config, graceful shutdown on SIGTERM. NOT DI modules/providers/guards (that is `nestjs`), NOT the type system or tsconfig (that is `typescript`), NOT REST contract design (that is `api-design`)."
|
|
4
4
|
tags: [nodejs, express, backend, async, error-handling]
|
|
5
5
|
recommends: [nestjs, typescript, api-design, error-handling, postgresdb]
|
|
6
6
|
origin: risco
|
|
@@ -8,24 +8,15 @@ origin: risco
|
|
|
8
8
|
|
|
9
9
|
# Node.js backend services
|
|
10
10
|
|
|
11
|
-
Stand up a plain Node.js HTTP/JSON service — `node:http` or Express 5 — that a person can read, test, and operate without a DI framework. This skill is about the runtime and the request lifecycle: how to lay out the code, how to keep async correct, how errors become status codes, how config fails fast, and how the process dies cleanly. The contract shape, the type system, and the data layer live elsewhere (see the
|
|
11
|
+
Stand up a plain Node.js HTTP/JSON service — `node:http` or Express 5 — that a person can read, test, and operate without a DI framework. This skill is about the runtime and the request lifecycle: how to lay out the code, how to keep async correct, how errors become status codes, how config fails fast, and how the process dies cleanly. The contract shape, the type system, and the data layer live elsewhere (see the boundary below).
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Boundary
|
|
14
14
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
- Choosing CommonJS vs ESM and pinning a runtime.
|
|
21
|
-
|
|
22
|
-
## Not this when
|
|
23
|
-
|
|
24
|
-
- The app is built around `@Module` / `@Injectable` / DI providers, guards, interceptors, pipes, exception filters → `../nestjs/SKILL.md`. Nest starts the moment the DI container appears; route away then, do not half-build it here.
|
|
25
|
-
- Pure TypeScript type system, generics, `tsconfig` → `../typescript/SKILL.md`. This skill uses TS but does not teach types.
|
|
26
|
-
- REST resource modeling, versioning, pagination, status-code semantics (framework-agnostic) → api-design. This skill *wires* the handlers; api-design decides the contract.
|
|
27
|
-
- Schema, queries, connection pool, migrations → `../postgresdb/SKILL.md` / prisma-orm / drizzle-orm. *Calling* a repository stays here; designing the table does not.
|
|
28
|
-
- Containerizing / shipping → docker / deployment. Choosing the logging/metrics/tracing stack → observability. This skill emits structured logs and a shutdown hook; it does not own the pipeline.
|
|
15
|
+
- The app is built around `@Module` / `@Injectable` / DI providers, guards, interceptors, pipes, exception filters → [`nestjs`](../nestjs/SKILL.md). Nest starts the moment the DI container appears; route away then, do not half-build it here.
|
|
16
|
+
- Pure TypeScript type system, generics, `tsconfig` → [`typescript`](../typescript/SKILL.md). This skill uses TS but does not teach types.
|
|
17
|
+
- REST resource modeling, versioning, pagination, status-code semantics (framework-agnostic) → [`api-design`](../api-design/SKILL.md). This skill *wires* the handlers; api-design decides the contract. Cross-cutting error taxonomy → [`error-handling`](../error-handling/SKILL.md).
|
|
18
|
+
- Schema, queries, connection pool, migrations → [`postgresdb`](../postgresdb/SKILL.md) / [`prisma-orm`](../prisma-orm/SKILL.md) / [`drizzle-orm`](../drizzle-orm/SKILL.md). *Calling* a repository stays here; designing the table does not.
|
|
19
|
+
- Containerizing / shipping → [`docker`](../docker/SKILL.md) / [`deployment`](../deployment/SKILL.md). Choosing the logging/metrics/tracing stack → [`observability`](../observability/SKILL.md). This skill emits structured logs and a shutdown hook; it does not own the pipeline.
|
|
29
20
|
|
|
30
21
|
## Decide first
|
|
31
22
|
|
|
@@ -33,7 +24,7 @@ Pick the runtime shape before writing code — the wrong choice is expensive to
|
|
|
33
24
|
|
|
34
25
|
| Situation | Choice | Why |
|
|
35
26
|
| --- | --- | --- |
|
|
36
|
-
| Needs DI/modules, large team, heavy cross-cutting | route to
|
|
27
|
+
| Needs DI/modules, large team, heavy cross-cutting | route to [`nestjs`](../nestjs/SKILL.md) | Don't reinvent a DI container by hand |
|
|
37
28
|
| Small/medium JSON API, want middleware + routing | Express 5 | Mature, async errors auto-forward (v5) |
|
|
38
29
|
| One tiny endpoint, zero deps, a healthcheck | `node:http` | No dependency surface to maintain |
|
|
39
30
|
| A library, not a server | not this skill | No request lifecycle to manage |
|
|
@@ -158,7 +149,7 @@ app.get("/users/:id", async (req, res) => {
|
|
|
158
149
|
});
|
|
159
150
|
```
|
|
160
151
|
|
|
161
|
-
The error handler placed before the route never sees the throw, so the response is whatever was half-written. Put it last. See `references/express5-migration.md` for the full v4→5 breaking-change checklist and the legacy v4 `asyncHandler` wrapper.
|
|
152
|
+
The error handler placed before the route never sees the throw, so the response is whatever was half-written. Put it last. See [`references/express5-migration.md`](references/express5-migration.md) for the full v4→5 breaking-change checklist, the middleware-order diagram, and the legacy v4 `asyncHandler` wrapper.
|
|
162
153
|
|
|
163
154
|
## Config & secrets
|
|
164
155
|
|
|
@@ -185,7 +176,7 @@ On SIGTERM the orchestrator gives you a brief window to finish. Drop nothing.
|
|
|
185
176
|
4. Close the DB pool and other resources.
|
|
186
177
|
5. `process.exit(0)`, with a force-exit timer as a backstop if drain stalls.
|
|
187
178
|
|
|
188
|
-
Expose `/healthz` (liveness — is the process up) separately from `/readyz` (readiness — should it receive traffic). They answer different questions; conflating them causes both false restarts and dropped requests during deploys. The
|
|
179
|
+
Expose `/healthz` (liveness — is the process up) separately from `/readyz` (readiness — should it receive traffic). They answer different questions; conflating them causes both false restarts and dropped requests during deploys. The complete copy-pasteable `server.ts` — signal handlers, `AbortController`, readiness gate, force-exit backstop — lives in [`references/graceful-shutdown.md`](references/graceful-shutdown.md).
|
|
189
180
|
|
|
190
181
|
```ts
|
|
191
182
|
// server.ts (sketch — full version in references/)
|
|
@@ -230,13 +221,9 @@ test("404 returns the error contract", async () => {
|
|
|
230
221
|
| `catch (e) {}` then continue | Swallows the failure, masks the bug | Re-throw, or map to an `AppError` |
|
|
231
222
|
| `process.exit()` without draining | Drops in-flight requests on deploy | SIGTERM → `server.close()` → abort → exit |
|
|
232
223
|
| Global `unhandledRejection` as control flow | Hides bugs, leaves process in a bad state | Log + exit there; fix the floating promise |
|
|
233
|
-
| Assuming Express 4 defaults | v5: `urlencoded` `extended:false`, `static` `dotfiles:"ignore"` | Read `references/express5-migration.md` |
|
|
224
|
+
| Assuming Express 4 defaults | v5: `urlencoded` `extended:false`, `static` `dotfiles:"ignore"` | Read [`references/express5-migration.md`](references/express5-migration.md) |
|
|
234
225
|
| Leaking stack/message in prod | Information disclosure | Stack only when `NODE_ENV !== "production"` |
|
|
235
226
|
|
|
236
|
-
##
|
|
237
|
-
|
|
238
|
-
- `references/express5-migration.md` — full Express 4→5 breaking changes, middleware-order diagram, the legacy v4 `asyncHandler` wrapper.
|
|
239
|
-
- `references/graceful-shutdown.md` — complete `server.ts`: signal handlers, `AbortController`, readiness gate, force-exit backstop.
|
|
240
|
-
- DI/modules/guards → `../nestjs/SKILL.md`. Type system/tsconfig → `../typescript/SKILL.md`. Data layer → `../postgresdb/SKILL.md`. Contract design → api-design. Cross-cutting error taxonomy → error-handling.
|
|
227
|
+
## Verify
|
|
241
228
|
|
|
242
229
|
`scripts/verify.sh` statically lints a produced repo for these rules (4-arg error handler last, no `listen()` in `app.ts`, `engines.node` supported, floating-promise heuristic). Advisory; hard-fails only on `listen()` in `app.ts` or a missing error handler.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: power-automate
|
|
3
|
-
description: "Use when operating Microsoft Power Automate cloud flows
|
|
3
|
+
description: "Use when operating Microsoft Power Automate cloud flows from code — create, enable, update, list or delete via the Dataverse Web API (`workflow` table, category 5) with Entra ID OAuth2, plus run-history debugging. NOT designing the flow definition (that is `automation-flows`), NOT picking a platform by billing model (that is `automation-strategy`)."
|
|
4
4
|
tags: [power-automate, dataverse, microsoft, flows, entra, oauth, mcp, m365, automation]
|
|
5
5
|
recommends: [automation-flows, automation-strategy, api-connector-builder, webhooks]
|
|
6
6
|
profiles: [full]
|
|
@@ -80,7 +80,7 @@ Two load-bearing parts:
|
|
|
80
80
|
- **`definition`** — a Logic Apps workflow definition: `triggers` (exactly one) then `actions`. This is the *design* artifact. Do not invent it from scratch here — get the trigger→actions→branch→error shape from `../automation-flows/SKILL.md`, then drop it into `definition`. Fastest reliable way to get a real one: build the flow once in the maker portal, export the solution, and copy its `clientdata`.
|
|
81
81
|
- **`connectionReferences`** — the map from the definition's connectors to actual connections. **A flow whose connection references are not authorized will not turn on.** In a solution these are connection-reference records the target environment must resolve; unresolved references are the #1 reason a `PATCH statecode=1` "succeeds" but the flow never runs.
|
|
82
82
|
|
|
83
|
-
**The trap:** `clientdata` must be *escaped into a string* before it goes in the request body — a nested object is rejected. In a script, `JSON.stringify(clientDataObject)` and assign the result; do not paste the object raw. Full annotated example in `references/dataverse-web-api.md`.
|
|
83
|
+
**The trap:** `clientdata` must be *escaped into a string* before it goes in the request body — a nested object is rejected. In a script, `JSON.stringify(clientDataObject)` and assign the result; do not paste the object raw. Full annotated example — plus the endpoint cheat-sheet (token, list/filter, create, enable, update, delete, ExportSolution, share), OData headers and error handling — in `references/dataverse-web-api.md`.
|
|
84
84
|
|
|
85
85
|
## Dynamic lifecycle — token → create → validate → enable → manage → delete
|
|
86
86
|
|
|
@@ -128,13 +128,17 @@ curl -s -X DELETE "$PA_DATAVERSE_URL/api/data/v9.2/workflows(<workflowid>)" \
|
|
|
128
128
|
|
|
129
129
|
**Debug a run** — Dataverse's `flowrun` table lists run records but not per-action I/O. To see *which action failed and with what payload*, use FlowStudio MCP: `list_live_flows` → `get_live_flow_runs` → `get_live_flow_run_action_outputs`. See `references/flowstudio-mcp-and-limits.md`.
|
|
130
130
|
|
|
131
|
-
##
|
|
131
|
+
## Boundaries — when it is not a flow you operate here
|
|
132
132
|
|
|
133
|
-
Power Automate is Microsoft's iPaaS across M365 and Dynamics; flows live in **Dataverse** and glue Outlook, Teams, SharePoint, Dynamics, and hundreds of connectors.
|
|
133
|
+
Power Automate is Microsoft's iPaaS across M365 and Dynamics; flows live in **Dataverse** and glue Outlook, Teams, SharePoint, Dynamics, and hundreds of connectors. This skill is for when the automation genuinely *is* a Power Automate flow you must operate by code. When it isn't:
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
- *"Send this email / read this calendar via Microsoft Graph from my own backend code"* — not a flow at all; build a typed Graph client with `../api-connector-builder/SKILL.md` (there is no first-party MS-Graph skill), or `../google-workspace/SKILL.md` for the Google equivalent. Same route for a general typed client with auth/pagination/backoff — this skill uses the Dataverse endpoints surgically, it does not build a client.
|
|
136
|
+
- *"Power Automate or n8n/Make/Zapier?"* — billing model and constraints decide that: `../automation-strategy/SKILL.md`, before you commit to operating here.
|
|
137
|
+
- *"Receive my flow's HTTP-trigger POST in my app"* — that inbound endpoint is `../webhooks/SKILL.md`; this skill triggers and operates flows, it does not build the receiver.
|
|
136
138
|
|
|
137
|
-
|
|
139
|
+
## Anti-patterns
|
|
140
|
+
|
|
141
|
+
| Anti-pattern | Why it bites | Do instead |
|
|
138
142
|
|---|---|---|
|
|
139
143
|
| Trying to CRUD a **My Flow** by code | Unsupported — silently impossible, not a bug you can fix | Move it into a Dataverse solution, or drive it by hand |
|
|
140
144
|
| `clientdata` sent as a nested object | Request rejected; the column expects an escaped **string** | Serialize (`JSON.stringify`) the definition+connectionReferences before sending |
|
|
@@ -144,13 +148,6 @@ Power Automate is Microsoft's iPaaS across M365 and Dynamics; flows live in **Da
|
|
|
144
148
|
| Hardcoding the Dataverse URL / secret | Env-specific, leaks in source | `.env`: `PA_DATAVERSE_URL`, `PA_TENANT_ID`, `PA_CLIENT_ID`, `PA_CLIENT_SECRET` |
|
|
145
149
|
| Assuming the Dataverse path is permanent | Power Platform API is superseding surfaces piecemeal | Re-check `api.powerplatform.com` coverage at author time; the split is fast-moving |
|
|
146
150
|
|
|
147
|
-
## Related skills
|
|
148
|
-
|
|
149
|
-
- **`../automation-flows/SKILL.md`** — design side: what the trigger→actions→branch→error should be, the importable definition. This skill *consumes* that shape as `clientdata.definition`. Design there, operate here.
|
|
150
|
-
- **`../automation-strategy/SKILL.md`** — choosing Power Automate vs n8n/Make/Zapier by billing and constraints. Decide there before you commit to operating here.
|
|
151
|
-
- **`../api-connector-builder/SKILL.md`** — a generic typed REST client with auth/pagination/backoff (including a Dataverse or MS Graph client). This skill uses the Dataverse API surgically; it does not build a general client.
|
|
152
|
-
- **`../webhooks/SKILL.md`** — building the inbound endpoint in *your* app that receives a flow's HTTP-trigger POST. This skill triggers/operates flows; it does not build the receiver.
|
|
153
|
-
|
|
154
151
|
## Checklist
|
|
155
152
|
|
|
156
153
|
- [ ] `.env` set: `PA_DATAVERSE_URL` (no trailing slash), `PA_TENANT_ID`, `PA_CLIENT_ID`, `PA_CLIENT_SECRET`.
|
|
@@ -161,9 +158,3 @@ Power Automate is Microsoft's iPaaS across M365 and Dynamics; flows live in **Da
|
|
|
161
158
|
- [ ] Flow enabled via `PATCH statecode=1` and verified on read-back.
|
|
162
159
|
- [ ] Solution **exported** before any `DELETE`.
|
|
163
160
|
- [ ] No secrets or org URLs hardcoded; FlowStudio MCP (if used) flagged as third-party.
|
|
164
|
-
|
|
165
|
-
## References
|
|
166
|
-
|
|
167
|
-
- `references/dataverse-web-api.md` — endpoint cheat-sheet (token, list/filter, create, enable, update, delete, ExportSolution, share), the full annotated `clientdata`, OData headers, and error handling.
|
|
168
|
-
- `references/entra-auth-setup.md` — app registration, service principal vs delegated user, the Dataverse application user + security role, `.default` vs `user_impersonation`, and common 401/403 causes.
|
|
169
|
-
- `references/flowstudio-mcp-and-limits.md` — FlowStudio MCP tools and auth (third-party), what it exposes that Dataverse doesn't, and the platform limits (My Flows, `api.flow.microsoft.com`, Power Platform API evolution).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: prisma-orm
|
|
3
|
-
description: "Use when modeling data or writing type-safe queries with Prisma ORM in TypeScript
|
|
3
|
+
description: "Use when modeling data or writing type-safe queries with Prisma ORM in TypeScript — `schema.prisma`, `prisma.config.ts`, the generated Prisma Client, and Prisma Migrate, including the v6 to v7 upgrade. NOT schema-as-TS with a SQL builder (that is `drizzle-orm`), NOT ORM-agnostic zero-downtime migration (that is `db-migrations`), NOT Postgres engine tuning (that is `postgresdb`)."
|
|
4
4
|
tags:
|
|
5
5
|
- prisma
|
|
6
6
|
- prisma-orm
|
|
@@ -286,8 +286,8 @@ Rules with teeth:
|
|
|
286
286
|
|
|
287
287
|
Failed-migration recovery, baselining an existing database, and the full Prisma 6 to 7
|
|
288
288
|
upgrade are in `references/migrations-and-v7-upgrade.md`. For ORM-independent evolution
|
|
289
|
-
strategy (expand/contract, dual-write, zero-downtime backfills) that is
|
|
290
|
-
|
|
289
|
+
strategy (expand/contract, dual-write, zero-downtime backfills) that is
|
|
290
|
+
`../db-migrations/SKILL.md`.
|
|
291
291
|
|
|
292
292
|
## Anti-patterns
|
|
293
293
|
|
|
@@ -311,10 +311,3 @@ Run `scripts/verify.sh <path>` to statically check emitted artifacts: it confirm
|
|
|
311
311
|
`prisma-client` generator + `output`, an adapter on the constructor, and flags
|
|
312
312
|
`$queryRawUnsafe` injection, `binaryTargets`, unbounded `findMany`, and wrong-ORM
|
|
313
313
|
contamination. Read-only; no database connection.
|
|
314
|
-
|
|
315
|
-
## References
|
|
316
|
-
|
|
317
|
-
- `references/queries-and-performance.md` — query cookbook, `relationLoadStrategy` matrix,
|
|
318
|
-
transactions, generated types, the perf checklist, and the raw-SQL safety matrix.
|
|
319
|
-
- `references/migrations-and-v7-upgrade.md` — migrate workflow detail, failed-migration
|
|
320
|
-
recovery, baselining, and the full Prisma 6 to 7 upgrade.
|
|
@@ -21,8 +21,8 @@ should_trigger:
|
|
|
21
21
|
why: Non-obvious v7 change — generated output path replaces the node_modules import.
|
|
22
22
|
- prompt: "Necessito fer la migració de Prisma a la versió 7, què he de canviar a schema.prisma i al client?"
|
|
23
23
|
why: >
|
|
24
|
-
Catalan phrasing
|
|
25
|
-
|
|
24
|
+
Catalan phrasing of the v6 to 7 upgrade (generator rename, output, adapter,
|
|
25
|
+
prisma.config.ts), which this skill owns.
|
|
26
26
|
|
|
27
27
|
should_not_trigger:
|
|
28
28
|
- prompt: "Set up the same schema using Drizzle's pgTable and drizzle-kit"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: procurement
|
|
3
|
-
description: "Use when a small operator must
|
|
3
|
+
description: "Use when a small operator must choose what to buy and from whom: pick a supplier, write an RFI/RFQ/RFP that returns comparable bids, score quotes on total cost of ownership, negotiate price and payment terms, or judge single-source risk. NOT redlining the purchase agreement (that is `contracts`), NOT the price you charge customers (that is `pricing`), NOT stock once it lands (that is `inventory`)."
|
|
4
4
|
tags: [procurement, sourcing, suppliers, rfq, negotiation, vendor-management]
|
|
5
5
|
recommends: [contracts, pricing, inventory, logistics-ops, invoicing, cost-tracking]
|
|
6
6
|
origin: risco
|
|
@@ -172,8 +172,3 @@ You own the decision and the deal. The moment it becomes something else, route:
|
|
|
172
172
|
- Tracking ongoing SaaS/subscription spend after a renewal decision → `../cost-tracking/SKILL.md`.
|
|
173
173
|
|
|
174
174
|
> Note on AI: generative tools can compress supplier *discovery* by up to ~90% — finding candidates fast. They do not replace the weighting, TCO model, risk segmentation, or negotiation. Use AI to widen the shortlist; keep the judgment human and on paper.
|
|
175
|
-
|
|
176
|
-
## references/
|
|
177
|
-
|
|
178
|
-
- `references/sourcing-requests.md` — copy-ready RFI/RFQ/RFP skeletons with the mandatory comparable-bid sections, plus invite and award/regret email templates.
|
|
179
|
-
- `references/scorecard-and-tco.md` — weighted-scorecard template, worked TCO comparison layout, supplier performance scorecard, SRM-cadence-by-quadrant table, and re-source trigger thresholds.
|
|
@@ -12,9 +12,9 @@ should_trigger:
|
|
|
12
12
|
- prompt: "We buy a critical component from only one supplier — how worried should I be?"
|
|
13
13
|
why: Single/sole-source concentration risk and the backup-plan requirement.
|
|
14
14
|
- prompt: "Negociar mejores condiciones de pago con nuestro proveedor."
|
|
15
|
-
why: Spanish
|
|
15
|
+
why: Asked in Spanish — payment-terms negotiation, trading a concession for extended terms.
|
|
16
16
|
- prompt: "Compara aquests proveïdors i munta una scorecard ponderada per decidir."
|
|
17
|
-
why: Catalan
|
|
17
|
+
why: Asked in Catalan — weighted-scorecard supplier comparison.
|
|
18
18
|
|
|
19
19
|
should_not_trigger:
|
|
20
20
|
- prompt: "Draft and redline the purchase agreement so we can sign it."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: react-native
|
|
3
|
-
description: "Use when writing the JS/TS
|
|
3
|
+
description: "Use when writing the JS/TS inside a React Native or Expo app — screens, Expo Router navigation, lists, Reanimated gestures, platform forks, offline state, native modules — or killing jank and render storms. NOT eas build/submit/OTA/config-plugin (that is `expo`), NOT a Dart app (that is `flutter`), NOT web React/DOM (that is `react` or `nextjs`)."
|
|
4
4
|
tags: [react-native, expo, mobile, ios, android, navigation, performance]
|
|
5
5
|
recommends: [expo, react, flutter, design, debug, performance]
|
|
6
6
|
origin: risco
|
|
@@ -8,11 +8,7 @@ origin: risco
|
|
|
8
8
|
|
|
9
9
|
# React Native (app code)
|
|
10
10
|
|
|
11
|
-
You write the code that runs *inside* the app: render, navigate, animate, list, persist, and author native modules.
|
|
12
|
-
|
|
13
|
-
## What this skill owns
|
|
14
|
-
|
|
15
|
-
Mobile is split across two skills by **verb**. Run the verb test before doing anything:
|
|
11
|
+
You write the code that runs *inside* the app: render, navigate, animate, list, persist, and author native modules. Mobile is split across two skills by **verb** — run the verb test before doing anything:
|
|
16
12
|
|
|
17
13
|
| Verb in the request | Skill |
|
|
18
14
|
|---|---|
|
|
@@ -149,7 +145,7 @@ Use Reanimated 4 CSS animations for simple declarative cases (fades, simple tran
|
|
|
149
145
|
|
|
150
146
|
- Small forks: `Platform.select({ ios: 12, android: 8 })` or `Platform.OS === 'ios'`.
|
|
151
147
|
- Whole-component forks: `Button.ios.tsx` / `Button.android.tsx` — the bundler picks the right one; import `./Button` with no extension.
|
|
152
|
-
- Safe area: use `react-native-safe-area-context` insets, not hardcoded notch padding. Why: insets differ per device and orientation.
|
|
148
|
+
- Safe area: use `react-native-safe-area-context` insets, not hardcoded notch padding. Why: insets differ per device and orientation. Palette, type scale and layout intent are not decided here → `../design/SKILL.md`.
|
|
153
149
|
- `KeyboardAvoidingView` behaves differently per platform — `padding` on iOS, often `height` or nothing on Android; test both, don't assume the iOS behavior ports.
|
|
154
150
|
- Set the status bar style explicitly per screen via `expo-status-bar`.
|
|
155
151
|
|
|
@@ -196,6 +192,7 @@ Full Expo Module (Swift + Kotlin + view), the Turbo Module codegen-spec walkthro
|
|
|
196
192
|
- Read **Hermes** stack traces from the bottom up; the JS frame that matters is usually above the native bridge frames.
|
|
197
193
|
- "Works on iOS, breaks on Android" (or vice versa) → run the platform-divergence checklist in `references/performance-debugging.md` before guessing.
|
|
198
194
|
- A red screen citing the interop layer is usually an old-architecture lib running under Fabric — update the lib or find a New-Arch-ready replacement; do **not** disable New Arch.
|
|
195
|
+
- A fault that resists all of the above needs systematic isolation, not more guesses → `../debug/SKILL.md`.
|
|
199
196
|
|
|
200
197
|
## Anti-patterns
|
|
201
198
|
|
|
@@ -211,10 +208,3 @@ Full Expo Module (Swift + Kotlin + view), the Turbo Module codegen-spec walkthro
|
|
|
211
208
|
| Index as list key | Breaks recycling, reorders rows on insert | Stable domain id |
|
|
212
209
|
| Doing native config / `eas.json` / OTA here | Wrong skill; this is app code | `../expo/SKILL.md` |
|
|
213
210
|
| Hardcoded notch/safe-area padding | Wrong on other devices/orientations | `react-native-safe-area-context` insets |
|
|
214
|
-
|
|
215
|
-
## Cross-references
|
|
216
|
-
|
|
217
|
-
- Building, signing, OTA, native config → `../expo/SKILL.md`
|
|
218
|
-
- Dart cross-platform alternative → `../flutter/SKILL.md`
|
|
219
|
-
- Layout/visual design decisions → `../design/SKILL.md`
|
|
220
|
-
- Systematic runtime fault isolation → `../debug/SKILL.md`
|
|
@@ -42,6 +42,7 @@ flag() { # message + matching lines
|
|
|
42
42
|
findings=1
|
|
43
43
|
printf '%s[finding]%s %s\n' "$YELLOW" "$RESET" "$1"
|
|
44
44
|
[ -n "${2:-}" ] && printf '%s\n' "$2" | sed 's/^/ /'
|
|
45
|
+
return 0 # never let a message-only finding trip set -e and skip the remaining checks
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
md_files() { # SKILL.md + every references/*.md
|
|
@@ -86,11 +87,13 @@ if [ -n "$bare" ]; then
|
|
|
86
87
|
done < "$SKILL"
|
|
87
88
|
fi
|
|
88
89
|
|
|
89
|
-
# 4) Description
|
|
90
|
+
# 4) Description shape: a "Use when/to" lead, a NOT-boundary, and no keyword trigger list
|
|
91
|
+
# (the model matches by meaning; a phrase list is per-turn cost for every install).
|
|
90
92
|
desc="$(grep -m1 -E '^description:' "$SKILL" 2>/dev/null || true)"
|
|
91
93
|
if [ -n "$desc" ]; then
|
|
92
|
-
printf '%s' "$desc" | grep -
|
|
94
|
+
printf '%s' "$desc" | grep -qE 'Use (when|to) ' || flag "description does not open with 'Use when/to'"
|
|
93
95
|
printf '%s' "$desc" | grep -qE 'NOT ' || flag "description missing a 'NOT <x> (that is <sibling>)' boundary"
|
|
96
|
+
printf '%s' "$desc" | grep -q 'Triggers:' && flag "description carries a 'Triggers:' keyword list -> delete it, the model matches by meaning" ""
|
|
94
97
|
fi
|
|
95
98
|
|
|
96
99
|
# 5) No cross-ref to a sibling that does not exist on disk next to this skill.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: reporting
|
|
3
|
-
description: "Use when
|
|
3
|
+
description: "Use when a recurring report must ship itself on a cadence — weekly digest, monthly exec pack, board pack — via a fetch→narrate→render→deliver pipeline with a schedule and a freshness gate. NOT a live view people slice (that is `dashboard`), NOT picking which KPIs to track (that is `kpi-framework`), NOT a one-off investigation (that is `analytics`)."
|
|
4
4
|
tags: [reporting, automated-reports, recurring, stakeholder-reporting, scheduled-delivery, data-analytics]
|
|
5
5
|
recommends: [dashboard, kpi-framework, analytics, automation-flows, email-connector, spreadsheet-ops, google-workspace, notion-connector, github-actions]
|
|
6
6
|
origin: risco
|
|
@@ -10,9 +10,10 @@ origin: risco
|
|
|
10
10
|
|
|
11
11
|
A report is a **push** artifact: a fixed snapshot that lands in someone's inbox or shared drive on a
|
|
12
12
|
cadence, the same shape every period, with no human assembling it. That is the whole job. If a human
|
|
13
|
-
opens a live view to slice numbers themselves, that is **pull** — a
|
|
14
|
-
line; almost every failed "reporting"
|
|
15
|
-
nobody can trust because the numbers went
|
|
13
|
+
opens a live view to slice numbers themselves, that is **pull** — a
|
|
14
|
+
[`dashboard`](../dashboard/SKILL.md), not a report. Hold that line; almost every failed "reporting"
|
|
15
|
+
project is a dashboard wearing a report's name, or a report nobody can trust because the numbers went
|
|
16
|
+
stale and no one noticed.
|
|
16
17
|
|
|
17
18
|
Your deliverable is a **runnable pipeline**, not advice: a template, a generation script, a schedule,
|
|
18
19
|
and a delivery step, with a freshness gate so it fails loud instead of shipping yesterday's numbers.
|
|
@@ -32,24 +33,23 @@ is a number no one can defend.
|
|
|
32
33
|
| **Owner** | Who gets paged when it breaks | a named person, not "the team" |
|
|
33
34
|
|
|
34
35
|
Rule: you **consume** an agreed metric set — you do not adjudicate which KPIs matter. If the ask is
|
|
35
|
-
"which metrics should we even track?", that is kpi-framework, not this
|
|
36
|
-
source and its owner so a wrong number has an address.
|
|
36
|
+
"which metrics should we even track?", that is [`kpi-framework`](../kpi-framework/SKILL.md), not this
|
|
37
|
+
skill. The contract names the source and its owner so a wrong number has an address.
|
|
37
38
|
|
|
38
39
|
## Decide: push report vs live dashboard (this branches — settle it first)
|
|
39
40
|
|
|
40
|
-
Audiences want a
|
|
41
|
-
|
|
41
|
+
Audiences want a citable snapshot for the period more often than a live feed — that is why push wins
|
|
42
|
+
for exec summaries, weekly reviews, and finance close packs.
|
|
42
43
|
|
|
43
44
|
| Signal in the ask | Route |
|
|
44
45
|
| --- | --- |
|
|
45
46
|
| "Same summary, every week/month/quarter" | **reporting** (here) |
|
|
46
47
|
| "Consistent snapshot the board can cite in a meeting" | **reporting** (here) |
|
|
47
48
|
| "It must arrive even if no one logs in" | **reporting** (here) |
|
|
48
|
-
| "A screen people open to filter/drill live" |
|
|
49
|
-
| "Self-serve, slice by region/date on demand" |
|
|
49
|
+
| "A screen people open to filter/drill live" | [`dashboard`](../dashboard/SKILL.md) |
|
|
50
|
+
| "Self-serve, slice by region/date on demand" | [`dashboard`](../dashboard/SKILL.md) |
|
|
50
51
|
|
|
51
|
-
When both are wanted, build the report
|
|
52
|
-
email a dashboard link and call it a report — see the anti-patterns table.
|
|
52
|
+
When both are wanted, build the report and let it link to the dashboard as a "go deeper" footer.
|
|
53
53
|
|
|
54
54
|
## Pick the artifact format
|
|
55
55
|
|
|
@@ -120,7 +120,7 @@ Bad → Good, the difference that decides whether the report is useful:
|
|
|
120
120
|
- **Bad:** a table row `Revenue | 248,300 | 201,400`. The reader must do the math and guess if it matters.
|
|
121
121
|
- **Good:** "Revenue up 23.3% WoW (€248,300 from €201,400) — investigate: driven by the enterprise renewal that won't recur next week."
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
The numbers are the evidence; the sentence is the report.
|
|
124
124
|
|
|
125
125
|
## Schedule + reliability gate (where reports actually die)
|
|
126
126
|
|
|
@@ -145,7 +145,8 @@ does not teach scheduling in general. The actual transport (SMTP/Gmail send) bel
|
|
|
145
145
|
|
|
146
146
|
- [ ] **Freshness gate before send** — assert the source is newer than the last period; if stale, do
|
|
147
147
|
NOT send, raise instead. A report that consumes dirty data is not this skill's job to clean —
|
|
148
|
-
that is data-cleaning; this gate only refuses to ship
|
|
148
|
+
that is [`data-cleaning`](../data-cleaning/SKILL.md); this gate only refuses to ship
|
|
149
|
+
known-stale numbers.
|
|
149
150
|
- [ ] **Fail loud** — on any error, alert the owner (the report not arriving is itself a silent failure).
|
|
150
151
|
- [ ] **Idempotent run** — re-running for the same period produces the same artifact, no duplicate send.
|
|
151
152
|
- [ ] **Dead-report cleanup** — if no one opened the last N editions, kill the schedule. Unread reports
|
|
@@ -161,18 +162,15 @@ does not teach scheduling in general. The actual transport (SMTP/Gmail send) bel
|
|
|
161
162
|
| Raw metric dump, no narrative | Reader does the math, misses what changed, stops opening it | Exec summary + 3 takeaways + a "so what" per section |
|
|
162
163
|
| Schedule with no failure alert | A broken job is invisible for weeks; the report just stops | Fail loud to the named owner on any error |
|
|
163
164
|
| A template forked per recipient | Layout change must be made N times; they drift | Single template scoped by `params` |
|
|
164
|
-
| Redefining KPIs inside the report | The report quietly becomes the metric authority, numbers diverge | Consume an agreed set; defer definition to kpi-framework |
|
|
165
|
+
| Redefining KPIs inside the report | The report quietly becomes the metric authority, numbers diverge | Consume an agreed set; defer definition to [`kpi-framework`](../kpi-framework/SKILL.md) |
|
|
165
166
|
| Unpinned WeasyPrint / render lib | A minor bump reflows the board pack with no warning | Pin (WeasyPrint 68.1) and re-check PyPI before changing |
|
|
166
167
|
| Hand-assembling the digest weekly | It breaks the week the owner is on leave | Automate the pipeline end to end; a human only reads it |
|
|
167
168
|
|
|
168
169
|
## Verify
|
|
169
170
|
|
|
170
171
|
Run `scripts/verify.sh` (read-only; pass a path to a generated pipeline directory, or run in it). It
|
|
171
|
-
confirms a Jinja2 template
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
References: [`pipeline.md`](references/pipeline.md) — full template, chart embed, per-recipient loop,
|
|
178
|
-
GitHub Actions `schedule:` YAML, freshness gate, and failure alert.
|
|
172
|
+
confirms a Jinja2 template renders against a sample context without error, the generation script
|
|
173
|
+
produces a non-empty PDF/HTML artifact, a schedule definition exists (a crontab line or a
|
|
174
|
+
`.github/workflows/*.yml` with a `schedule:` block), and a delivery step is wired. It soft-warns if no
|
|
175
|
+
freshness/failure gate is detected, and exits 0 on an empty/clean target — nothing to check is not a
|
|
176
|
+
failure.
|
package/skills/roast-me/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: roast-me
|
|
3
|
-
description: "Use when
|
|
3
|
+
description: "Use when someone wants an honest, comedic audit of their own prompting — reads their past agent transcripts, scores prompt quality and compute efficiency, names their worst habits, builds a model-selection cheat sheet. NOT reviewing code an agent produced (that is `code-review`), NOT prompting technique in general (that is `prompt-engineering`)."
|
|
4
4
|
tags: [prompting, self-audit, compute-efficiency, ai-hygiene, learning]
|
|
5
5
|
recommends: [prompt-engineering, code-review, context-budget]
|
|
6
6
|
profiles: [full]
|
|
@@ -9,7 +9,7 @@ origin: risco
|
|
|
9
9
|
|
|
10
10
|
# roast-me — audit your prompting, score yourself, stop burning money
|
|
11
11
|
|
|
12
|
-
You are the **prompt auditor**. Your target is not the user's code — it is their *prompting behaviour
|
|
12
|
+
You are the **prompt auditor**. Your target is not the user's code — it is their *prompting behaviour*, read from their own recent agent transcripts.
|
|
13
13
|
|
|
14
14
|
Every run follows five phases. Execute them in order.
|
|
15
15
|
|
|
@@ -115,9 +115,7 @@ Score History:
|
|
|
115
115
|
2026-06-08 73/100 (C) +5↑ 35/100 (F) The 3W Rule
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
Output the roast report as formatted markdown.
|
|
119
|
-
|
|
120
|
-
Done.
|
|
118
|
+
Output the roast report as formatted markdown.
|
|
121
119
|
|
|
122
120
|
## Orientación (siempre)
|
|
123
121
|
|
|
@@ -9,7 +9,7 @@ skill: roast-me
|
|
|
9
9
|
|
|
10
10
|
should_trigger:
|
|
11
11
|
- prompt: "Roast me."
|
|
12
|
-
why: "Canonical
|
|
12
|
+
why: "Canonical invocation — the shortest possible ask for exactly this skill's job. Must fire immediately and run the five-phase pipeline."
|
|
13
13
|
|
|
14
14
|
- prompt: "Audit my prompting habits over the last two weeks."
|
|
15
15
|
why: "Situation-first phrasing with a custom time window — roast-me owns both the 'audit prompting' job and the --days N parameter."
|
|
@@ -18,10 +18,10 @@ should_trigger:
|
|
|
18
18
|
why: "Dual concern (prompt quality + cost) phrased as a question — maps directly to the two scores roast-me produces. No mention of 'roast' keyword."
|
|
19
19
|
|
|
20
20
|
- prompt: "Analiza mis prompts de la última semana y dime dónde soy malo."
|
|
21
|
-
why: "Spanish-language
|
|
21
|
+
why: "Spanish-language request — rsc users write Spanish; routing must survive translation on meaning alone."
|
|
22
22
|
|
|
23
23
|
- prompt: "Puntua els meus prompts i digue'm quins hàbits hauria de canviar."
|
|
24
|
-
why: "Catalan-language
|
|
24
|
+
why: "Catalan-language request — a non-obvious language variant that must route on meaning, with no keyword resembling the skill id."
|
|
25
25
|
|
|
26
26
|
- prompt: "How much am I burning on model costs? Show me where I overspend."
|
|
27
27
|
why: "Compute-efficiency angle only, no prompting-quality framing — roast-me's compute score and cheat sheet are the direct answer."
|
package/skills/ruby/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ruby
|
|
3
|
-
description: "Use when writing
|
|
3
|
+
description: "Use when writing or refactoring plain Ruby outside Rails — scripts, CLIs, gems, libraries: Enumerable chains and blocks, module mixins and value objects, Bundler/gemspec packaging, whether metaprogramming earns its keep, Minitest or RSpec, Ruby 3.4/4.0 frozen-string hygiene. NOT Rails, ActiveRecord, or ActiveSupport idioms (that is `rails`)."
|
|
4
4
|
tags: [ruby, gems, bundler, metaprogramming, rspec, minitest, enumerable]
|
|
5
5
|
recommends: [rails, testing-web, secure-coding]
|
|
6
6
|
profiles: []
|
|
@@ -14,31 +14,18 @@ leaning on `Enumerable` and `Comparable` instead of hand-rolled loops, with
|
|
|
14
14
|
`frozen_string_literal` hygiene and a real `Gemfile`/`.gemspec` when you package.
|
|
15
15
|
|
|
16
16
|
This is **Ruby the language and its non-Rails ecosystem** — blocks, modules, gems,
|
|
17
|
-
metaprogramming, Minitest/RSpec.
|
|
18
|
-
|
|
17
|
+
metaprogramming, Minitest/RSpec. Delegate: Rails apps, ActiveRecord models, controllers,
|
|
18
|
+
migrations, views, Hotwire — anything that loads Rails or uses ActiveSupport/ActiveRecord
|
|
19
|
+
idioms — to [`rails`](../rails/SKILL.md); the same task in another language to
|
|
20
|
+
[`python`](../python/SKILL.md), [`go`](../go/SKILL.md), [`rust`](../rust/SKILL.md),
|
|
21
|
+
[`elixir`](../elixir/SKILL.md), [`php`](../php/SKILL.md) or
|
|
22
|
+
[`typescript`](../typescript/SKILL.md); the CI pipeline that runs your Ruby tests to
|
|
23
|
+
[`github-actions`](../github-actions/SKILL.md) — this skill writes the tests, not the workflow.
|
|
19
24
|
|
|
20
25
|
Targets **Ruby 4.0** (released 2025-12-25) on **3.4** semantics: Prism is the default
|
|
21
26
|
parser, string literals warn on mutation without a magic comment, `it` is an implicit
|
|
22
27
|
block param, and `Set` is now a core class.
|
|
23
28
|
|
|
24
|
-
## When to use / When NOT to use
|
|
25
|
-
|
|
26
|
-
**Use when:**
|
|
27
|
-
|
|
28
|
-
- Authoring or refactoring any plain-Ruby `.rb` file, CLI, script, gem, or library.
|
|
29
|
-
- Turning imperative loops into `Enumerable` chains (`map`/`select`/`reduce`/`each_with_object`/`group_by`).
|
|
30
|
-
- Designing module mixins, `Comparable`/`Enumerable` inclusion, refinements, or value objects (`Struct`/`Data`).
|
|
31
|
-
- Setting up a gem: `bundle gem`, `.gemspec`, SemVer, version constraints, publishing to RubyGems.
|
|
32
|
-
- Deciding whether metaprogramming (`method_missing`, `define_method`, `instance_eval`, DSLs) earns its keep.
|
|
33
|
-
- Writing tests with Minitest or RSpec, wiring RuboCop/Standard, or adding RBS/Sorbet typing.
|
|
34
|
-
|
|
35
|
-
**When NOT to use (delegate):**
|
|
36
|
-
|
|
37
|
-
- Rails apps, ActiveRecord models, controllers, migrations, views, Hotwire -> `rails`.
|
|
38
|
-
The hard line: anything that loads Rails or uses ActiveSupport/ActiveRecord idioms.
|
|
39
|
-
- The same task in another language -> `python`, `go`, `rust`, `elixir`, `php`, `typescript`.
|
|
40
|
-
- A CI pipeline that runs your Ruby tests -> `github-actions` (this skill writes the tests, not the workflow).
|
|
41
|
-
|
|
42
29
|
## Mental model
|
|
43
30
|
|
|
44
31
|
Internalize these before writing a line:
|
|
@@ -291,7 +278,8 @@ examples with `let`/`subject`/`context` are in
|
|
|
291
278
|
- **Types:** two coexisting systems — **RBS** (official signatures in separate `.rbs`
|
|
292
279
|
files, checked by Steep) and **Sorbet** (inline `sig` blocks, with experimental
|
|
293
280
|
inline-RBS-comment support). Add types only on a library's public surface or a hot,
|
|
294
|
-
bug-prone core — not on throwaway scripts.
|
|
281
|
+
bug-prone core — not on throwaway scripts. RuboCop vs Standard config sits in
|
|
282
|
+
[references/gems-and-testing.md](references/gems-and-testing.md).
|
|
295
283
|
|
|
296
284
|
## Anti-patterns
|
|
297
285
|
|
|
@@ -305,12 +293,3 @@ examples with `let`/`subject`/`context` are in
|
|
|
305
293
|
| Not committing `Gemfile.lock` for an app | Non-reproducible installs across machines | Commit it for apps; omit only for library gems |
|
|
306
294
|
| `eval` of user-derived input | Remote code execution | Parse explicitly; never `eval` untrusted data |
|
|
307
295
|
| Over-DSLing config a Hash would serve | Hidden control flow, slow `method_missing` | A plain Hash or `Data` object |
|
|
308
|
-
|
|
309
|
-
## References
|
|
310
|
-
|
|
311
|
-
- [references/metaprogramming.md](references/metaprogramming.md) — `define_method`,
|
|
312
|
-
`method_missing` + `respond_to_missing?`, `instance_eval`/`class_eval`, building a DSL,
|
|
313
|
-
refinements vs monkey-patching, `prepend` wrapping.
|
|
314
|
-
- [references/gems-and-testing.md](references/gems-and-testing.md) — full `bundle gem`
|
|
315
|
-
tree and `.gemspec`, SemVer + `~>`, publishing, Rakefile, full Minitest + RSpec files,
|
|
316
|
-
RuboCop vs Standard config.
|