@ericrisco/rsc 0.1.49 → 0.1.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.49",
2
+ "version": "0.1.51",
3
3
  "counts": {
4
4
  "skills": 258
5
5
  },
@@ -1802,7 +1802,7 @@
1802
1802
  },
1803
1803
  {
1804
1804
  "id": "forecasting",
1805
- "description": "Use when you need to project sales, demand, units, revenue, signups or traffic forward from historical data and report a defensible number with an error band. Triggers: 'forecast next quarter's sales', 'how many units of SKU X next month', 'project revenue 12 months with a confidence band', 'is our forecast actually better than just repeating last quarter', lumpy/intermittent demand with lots of zero-sales weeks, 'prevé las ventas del próximo trimestre', 'prediu la demanda del proper mes per producte'. NOT building an assumption-driven P&L (that is financial-model), NOT sizing reorder points or safety stock (that is inventory).",
1805
+ "description": "Use when projecting history forward — sales, demand, units, revenue, signups, traffic — into a defensible number with an error band: method by data shape, rolling-origin backtest, MASE vs the naive baseline. NOT an assumption-driven P&L or runway model (that is `financial-model`), NOT sizing reorder points or safety stock (that is `inventory`).",
1806
1806
  "tags": [
1807
1807
  "forecasting",
1808
1808
  "demand-planning",
@@ -1869,7 +1869,7 @@
1869
1869
  },
1870
1870
  {
1871
1871
  "id": "game-storytelling",
1872
- "description": "Use when designing a game's STORY as an interactive system: premise, theme and narrative pillars; branching narrative and meaningful choice; dialogue trees with state and flags; quests, objectives and fail states; worldbuilding; environmental and systemic storytelling; and keeping story in harmony with play (avoiding ludonarrative dissonance). Engine-agnostic — it designs the narrative graph, variables and beats, then hands the wiring to the engine skill. Triggers: 'write my game's story/premise', 'branching narrative', 'dialogue system/tree', 'quest structure', 'worldbuilding', 'meaningful choices', 'illusion of choice', 'Ink/Yarn Spinner/Twine/articy narrative', 'story keeps fighting the gameplay'. NOT core mechanics, systems or balance (that's game-design); NOT spatial/level layout or encounter placement (that's level-design); NOT the actual dialogue-node code, save format or plugin wiring inside an engine (that's godot/unity/unreal).",
1872
+ "description": "Use when a game's story is the work: premise and pillars, branching topology, meaningful choice, dialogue state, quests, environmental storytelling, ludonarrative harmony. Author portable — engine wiring is `godot`/`unity`/`unreal`. NOT the mechanics and economy the story serves (that is `game-design`), NOT level layout (that is `level-design`).",
1873
1873
  "tags": [
1874
1874
  "game",
1875
1875
  "narrative",
@@ -1970,7 +1970,7 @@
1970
1970
  },
1971
1971
  {
1972
1972
  "id": "gamedev-shipping",
1973
- "description": "Use when exporting, building, packaging, or publishing a game — per engine (Godot export templates, Unity Build Profiles, Unreal Shipping vs Development) and per platform: desktop (Windows/macOS/Linux; macOS codesign + notarytool notarization), web (the COOP same-origin + COEP require-corp headers threaded SharedArrayBuffer WebAssembly builds need, and that Godot's C#/.NET edition can't export to web), mobile (Android JDK 17 build template, AAB vs APK, release keystore; iOS provisioning). Also store prep (icons/splash, metadata, age ratings, AAB for Play, Mac App Store, Steamworks/SteamPipe, itch.io butler), headless-export CI/CD, build/version numbers, and ship-time size/startup optimization. Triggers: 'export my game', 'build for Steam', 'ship to web/mobile', 'publish to the Play Store', 'notarize my Mac build', 'itch.io upload', 'SharedArrayBuffer is not defined'. NOT for writing gameplay/runtime code (that's the engine skill — godot/unity/unreal) or hosting a normal web app/API/container (→ deployment).",
1973
+ "description": "Use when exporting, packaging, signing, or publishing a game — export presets per engine, macOS notarization, cross-origin isolation for threaded web builds, Android AAB/keystore, iOS provisioning, store submission (Steam, Play, App Store, itch.io), headless build CI. NOT gameplay code inside the artifact (that is `godot`, `unity`, `unreal`), NOT hosting a web app or container (that is `deployment`).",
1974
1974
  "tags": [
1975
1975
  "export",
1976
1976
  "build",
@@ -2103,7 +2103,7 @@
2103
2103
  },
2104
2104
  {
2105
2105
  "id": "godot",
2106
- "description": "Use when writing, reviewing, or debugging Godot 4.x games in GDScript (typed) or C# — nodes/scenes/custom Resources, autoload singletons and an EventBus, signals via Callable, @onready/@export/@tool, static typing, CharacterBody2D/3D + velocity + move_and_slide(), _process vs _physics_process, .tscn/.tres text formats, and headless GUT/gdUnit4 tests. Enforces Godot 4 APIs and rejects Godot 3 leftovers: yield→await, onready→@onready, .instance()→.instantiate(), KinematicBody→CharacterBody, Spatial→Node3D, string connect(\\\"sig\\\",obj,\\\"m\\\")→Callable. Triggers: 'write a Godot player controller', 'my move_and_slide does nothing', 'port this Godot 3 script to 4', 'connect a signal in Godot', 'GDScript won't type-check', 'CharacterBody2D won't move', 'add an autoload', 'escribe un script de Godot', 'por qué no se mueve mi personaje'. NOT Unity MonoBehaviour or Unreal (route to unity/unreal); NOT pure C++/CMake tooling unrelated to GDExtension (that is cpp); NOT shader code in .gdshader (that is gamedev-shaders).",
2106
+ "description": "Use when writing, reviewing, or debugging Godot 4.x games in GDScript or C# — scenes, nodes, custom Resources, autoload/EventBus signals, typed GDScript, CharacterBody2D/3D movement, GUT/gdUnit4 — or porting Godot 3 APIs to 4. NOT Unity/Unreal (that is `unity`/`unreal`), NOT `.gdshader` code (`gamedev-shaders`), NOT GDExtension C++ tooling (`cpp`).",
2107
2107
  "tags": [
2108
2108
  "godot",
2109
2109
  "gdscript",
@@ -2150,7 +2150,7 @@
2150
2150
  },
2151
2151
  {
2152
2152
  "id": "grants",
2153
- "description": "Use when the goal is non-dilutive public or foundation funding — money you neither repay nor give equity for — and you must find a fit call, decide go/no-go, register an eligible entity, or write the application a reviewer scores against a published rubric (needs statement, logic model, SMART objectives, impact narrative, budget justification, LOI). Symptoms: a call with an Excellence/Impact/Implementation grid, a 3/5-per-criterion threshold, an indirect-cost line, a SAM.gov/UEI or BDNS lookup, an LOI that filters you before the full proposal. Triggers: 'find grants we qualify for', 'write the impact section so it scores above threshold', 'should we even bother applying to this call', 'build the budget justification', 'write a Letter of Inquiry', 'buscar la convocatòria a la BDNS', 'redactar la solicitud de subvención'. NOT equity rounds or investor pitches (that is fundraising), NOT a paying-customer SOW (that is proposals).",
2153
+ "description": "Use when pursuing non-dilutive public or foundation funding — money you neither repay nor give equity for: finding a fit call, go/no-go, registration (UEI/PIC/BDNS), or writing the rubric-scored application, logic model, budget justification, or LOI. NOT an equity round (that is `fundraising`), NOT a paying-customer SOW (that is `proposals`).",
2154
2154
  "tags": [
2155
2155
  "grants",
2156
2156
  "subsidies",
@@ -2170,7 +2170,7 @@
2170
2170
  },
2171
2171
  {
2172
2172
  "id": "harness",
2173
- "description": "Use to control, govern or maintain a workspace's harness — software or non-code (a company, an ops desk, a knowledge vault). The harness is the control plane: the `01-TOOLS/` tooling layer, the `02-DOCS/` chaos→knowledge wiki, and the root Knowledge map. It audits, migrates legacy `XX-*` folders, scaffolds provider tooling, sweeps the inbox, and generates root CLAUDE.md/AGENTS.md. Brownfield-first. NOT the bootstrap front door (that is `init`, which hands off here).",
2173
+ "description": "Use when governing a workspace's control plane, code or not — the `01-TOOLS/` tooling layer, the `02-DOCS/` chaos→knowledge wiki, the root Knowledge map. Audits it, migrates legacy `XX-*` folders, scaffolds provider tooling, sweeps the inbox, writes root CLAUDE.md/AGENTS.md. NOT the bootstrap front door (that is `init`, which hands off here).",
2174
2174
  "tags": [
2175
2175
  "harness",
2176
2176
  "company",
@@ -2214,7 +2214,7 @@
2214
2214
  },
2215
2215
  {
2216
2216
  "id": "hiring",
2217
- "description": "Use when there's an open role and you need to write the job post, screen inbound candidates, structure the interview loop, or build a scorecard to reach a fair hire decision; symptoms: gut-feel ratings, every interviewer asking the same question, a bloated requirements list, no consistent screen. Triggers: 'write a job description', 'screen these CVs', 'build an interview scorecard', 'structure the interview panel', 'redacta la oferta de empleo', 'necesito una scorecard', plus the non-obvious 'four people interviewed and we still can't decide' and 'is our AI résumé filter legal'. NOT managing the person after they're hired — onboarding, payroll, performance (that is people-ops).",
2217
+ "description": "Use when a role is open and you must write the job post, screen inbound candidates, structure the interview loop, or score them to a defensible Hire / On-Hold / No-Hire — including whether an AI résumé filter is legal. NOT after the offer is accepted — onboarding, payroll, performance (that is `people-ops`), NOT offer terms (that is `contracts`).",
2218
2218
  "tags": [
2219
2219
  "hiring",
2220
2220
  "recruiting",
@@ -2315,7 +2315,7 @@
2315
2315
  },
2316
2316
  {
2317
2317
  "id": "instagram-api",
2318
- "description": "Use when wiring an agent into Instagram's Graph API to publish a Reel from a video URL, pull per-media insights (reach, views, watch-time, saves, shares, total_interactions), check the 24-hour publish cap, or ingest Reel performance into 02-DOCS/wiki/shortform. Triggers: 'publish this Reel via the API', 'pull reach and average watch time for these media IDs', 'why does /insights?metric=plays return an error', 'my container is stuck IN_PROGRESS', 'how many posts left in the 24h publish window', 'publica este Reel por la API', 'ingesta el rendimiento dels Reels al wiki'. NOT TikTok publishing (that is tiktok-api), NOT a posting calendar/cadence (that is social-publisher), NOT YouTube uploads/stats (that is youtube-api).",
2318
+ "description": "Use when wiring an agent into Instagram's Graph API: publishing a Reel through the create/poll/publish container dance, reading per-media insights, checking the 24h publish cap, or ingesting Reel metrics into 02-DOCS/wiki/shortform. NOT TikTok (that is `tiktok-api`), NOT YouTube (that is `youtube-api`), NOT cross-platform cadence (that is `social-publisher`).",
2319
2319
  "tags": [
2320
2320
  "instagram",
2321
2321
  "graph-api",
@@ -2740,7 +2740,7 @@
2740
2740
  },
2741
2741
  {
2742
2742
  "id": "machine-learning",
2743
- "description": "Use when the task is a classic/tabular machine-learning problem — predict a column from rows of features with trees and scikit-learn: fit a RandomForest / XGBoost / LightGBM classifier or regressor, build a leak-proof Pipeline + ColumnTransformer, choose a cross-validation scheme (stratified / k-fold / time-series / grouped), pick the right metric on imbalanced classes (precision/recall/F1/ROC-AUC/PR-AUC, not accuracy), or debug a model that aced CV then collapsed in production. Triggers: 'train a model to predict churn/fraud/price', 'my ROC-AUC is 0.99 — is that leakage', 'which metric for imbalanced classes', 'cross-validation without leaking', 'XGBoost vs LightGBM', 'add a DummyClassifier baseline', 'entrena un modelo de clasificación tabular con scikit-learn'. NOT neural-net / PyTorch training (that is deep-learning), NOT cleaning the raw dirty table first (that is data-cleaning), NOT BI dashboards or forecasting a dated series (that is analytics/forecasting), NOT text/token modeling (that is nlp).",
2743
+ "description": "Use when predicting a column from rows of tabular features with classic models — scikit-learn pipelines, RandomForest, XGBoost/LightGBM, leak-free cross-validation, metrics for imbalanced classes, or a model that aced CV then collapsed in production. NOT PyTorch neural nets (that is `deep-learning`), NOT cleaning the dirty table first (that is `data-cleaning`), NOT forecasting a dated series (that is `forecasting`), NOT text/token modeling (that is `nlp`).",
2744
2744
  "tags": [
2745
2745
  "machine-learning",
2746
2746
  "scikit-learn",
@@ -3196,7 +3196,7 @@
3196
3196
  },
3197
3197
  {
3198
3198
  "id": "observability",
3199
- "description": "Use when instrumenting a service from the inside so an incident can be explained from telemetry alone — wiring OpenTelemetry logs, metrics and traces, standing up a Collector, exporting via OTLP, and defining telemetry-driven alerts. Triggers: 'add OpenTelemetry to this service', 'we can't tell why requests are slow across services — add distributed tracing', 'replace our print/console.log with structured logs correlated to traces', 'stand up an OTel Collector and export to Grafana/Datadog/Honeycomb', 'instrument our LLM calls so each request is a span with token counts', 'define RED metrics and a burn-rate alert from the telemetry', 'instrumenta el servei amb OpenTelemetry i exporta a Grafana', 'añade trazas distribuidas y métricas'. NOT outside-in uptime probes, on-call rotation, or who-gets-paged (that is monitoring).",
3199
+ "description": "Use when instrumenting a service from the inside so an incident can be explained from telemetry alone — wiring OpenTelemetry logs, metrics and traces, standing up a Collector, exporting via OTLP, and defining telemetry-driven alerts. NOT outside-in uptime probes, on-call rotation, or who-gets-paged (that is `monitoring`).",
3200
3200
  "tags": [
3201
3201
  "observability",
3202
3202
  "opentelemetry",
@@ -3662,7 +3662,7 @@
3662
3662
  },
3663
3663
  {
3664
3664
  "id": "rag",
3665
- "description": "Use when building grounded Q&A over your own documents — handbook, support tickets, PDFs, policies — and the answers must come only from the corpus with citations; when retrieval surfaces the right document but the answer is still wrong; when the model invents facts that are not in the sources; when you need to measure whether retrieval is any good; when the right document is found but the wrong passage is used. Triggers: 'build a bot that answers from our docs with citations', 'my RAG returns the right document but the answer is wrong', 'how do I stop the model hallucinating facts not in the corpus', 'context recall vs context precision', 'add contextual retrieval / prepend chunk context before embedding', 'hybrid search plus rerank pipeline', 'respuestas con citas sobre nuestros documentos', 'el bot s'inventa coses que no surten als documents'. NOT operating the vector store itself — collection schema, HNSW ef_search, quantization (that is vector-db).",
3665
+ "description": "Use when building grounded Q&A over your own corpus — chunk, retrieve hybrid, rerank, ground, cite chunk ids, refuse when the sources fall short — or when the right document is retrieved but the answer is still wrong, invented, or unmeasured. NOT operating the store itself — collection schema, HNSW ef_search, quantization (that is `vector-db`).",
3666
3666
  "tags": [
3667
3667
  "rag",
3668
3668
  "retrieval-augmented-generation",
@@ -4664,7 +4664,7 @@
4664
4664
  },
4665
4665
  {
4666
4666
  "id": "tauri",
4667
- "description": "Use when building a lightweight cross-platform desktop (or v2 mobile) app with Tauri — a Rust core plus the OS-native WebView — wiring Rust commands and IPC, streaming data to the frontend, locking down the capabilities/permissions security model, or bundling and auto-updating tiny signed binaries. Triggers: 'build a Tauri app', 'expose a Rust command to my frontend', 'invoke from JS', 'tauri.conf.json', 'capabilities and permissions', 'stream download progress to the WebView', 'my command froze the UI', 'shrink my desktop binary vs Electron', 'set up the Tauri updater', 'crear una app d'escriptori lleugera amb Rust en lloc d'Electron', 'reducir el tamaño del binario de escritorio'. NOT a Chromium+Node desktop app that needs Node APIs in a main process (that is electron).",
4667
+ "description": "Use when building a lightweight cross-platform desktop (or v2 mobile) app with Tauri — a Rust core plus the OS-native WebView: Rust commands and IPC, streaming to the frontend, the default-deny capabilities/permissions ACL, bundling and signed auto-updates. NOT a Chromium+Node shell needing Node APIs in a main process (that is electron).",
4668
4668
  "tags": [
4669
4669
  "tauri",
4670
4670
  "desktop",
@@ -5140,7 +5140,7 @@
5140
5140
  },
5141
5141
  {
5142
5142
  "id": "webhooks",
5143
- "description": "Use when building the inbound side of a webhook — the HTTP endpoint that receives events a system pushes you, proves they are authentic, refuses to process the same one twice, and acks fast. Covers the mechanics every source shares: raw-body HMAC verification, ~5-min timestamp/replay window, idempotency on a stable event id, fast-ack-then-queue, retry/poison handling. Triggers: 'receive webhooks and process them safely', 'verify an incoming webhook signature', 'my signature verification fails even though the secret is correct', 'provider keeps retrying and we process the same event twice', 'handler times out under load, ack fast and queue', 'recibir webhooks entrantes', 'verificar la firma del webhook entrante', 'evitar procesar el mismo evento dos veces'. NOT the Stripe-Signature scheme (that is stripe), NOT email bounce/suppression hooks (that is email-connector), NOT outbound clients calling a third-party API (that is api-connector-builder), NOT what runs after the event lands (that is automation-flows).",
5143
+ "description": "Use when building the receiving end of a webhook — a provider-agnostic endpoint that proves pushed events are authentic and never processes one twice: raw-body HMAC, ~5-min replay window, idempotency on the event id, fast-ack-then-queue. NOT the Stripe-Signature scheme (that is stripe), NOT outbound clients you call (that is api-connector-builder).",
5144
5144
  "tags": [
5145
5145
  "webhooks",
5146
5146
  "inbound-webhooks",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ericrisco/rsc",
3
- "version": "0.1.49",
3
+ "version": "0.1.51",
4
4
  "description": "Eric Risco's agent-skills catalog as a granular, self-recommending CLI installer.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -114,16 +114,24 @@ Everything above is for the agent doing one skill. This half is for whoever is d
114
114
 
115
115
  ## Resuming, from nothing
116
116
 
117
- There is no state file to keep in sync, on purpose. **The remote branches are the ledger:**
117
+ There is no state file to keep in sync, on purpose. **The content is the ledger** — a migrated skill
118
+ no longer carries a `Triggers:` list in its description:
118
119
 
119
120
  ```bash
120
- # what is done
121
- git ls-remote --heads origin 'refs/heads/skill/*'
122
- # what is left = skills/ minus those, minus what is already merged to main
121
+ node -e "const fs=require('fs');const out=[];for(const d of fs.readdirSync('skills')){const p='skills/'+d+'/SKILL.md';if(!fs.existsSync(p))continue;const m=/^---\n([\s\S]*?)\n---/.exec(fs.readFileSync(p,'utf8'));if(m&&/Triggers:/i.test(m[1]))out.push(d)}console.log(out.join('\n'))"
123
122
  ```
124
123
 
125
- So a cold session resumes with: *read this brief, compute the skills with no `skill/*` branch, launch
126
- one agent per skill in its own worktree.* Nothing from any previous conversation is required.
124
+ So a cold session resumes with: *read this brief, run that, launch one agent per remaining skill in
125
+ its own worktree.* Nothing from any previous conversation is required.
126
+
127
+ **An earlier version of this section said the remote `skill/*` branches were the ledger. They are
128
+ not, and the failure is instructive**: once integration PRs started merging with `--delete-branch`,
129
+ the branches for finished skills vanished, so a branch-based check re-offered work that was already
130
+ on main — and an agent duly re-migrated `harness` a second time before anyone noticed. The
131
+ instruction was true when written and was invalidated by a later change to the merge flow, with
132
+ nothing to catch the drift. That is the same failure this whole migration keeps finding in the
133
+ catalog; the brief was not exempt from it. Prefer a check against the artifact over a check against
134
+ bookkeeping that something else can quietly change.
127
135
 
128
136
  ## Order: by profile, not alphabetically
129
137
 
File without changes
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: forecasting
3
- description: "Use when you need to project sales, demand, units, revenue, signups or traffic forward from historical data and report a defensible number with an error band. Triggers: 'forecast next quarter's sales', 'how many units of SKU X next month', 'project revenue 12 months with a confidence band', 'is our forecast actually better than just repeating last quarter', lumpy/intermittent demand with lots of zero-sales weeks, 'prevé las ventas del próximo trimestre', 'prediu la demanda del proper mes per producte'. NOT building an assumption-driven P&L (that is financial-model), NOT sizing reorder points or safety stock (that is inventory)."
3
+ description: "Use when projecting history forward — sales, demand, units, revenue, signups, traffic — into a defensible number with an error band: method by data shape, rolling-origin backtest, MASE vs the naive baseline. NOT an assumption-driven P&L or runway model (that is `financial-model`), NOT sizing reorder points or safety stock (that is `inventory`)."
4
4
  tags: [forecasting, demand-planning, time-series, sales-forecast, statsforecast]
5
5
  recommends: [inventory, financial-model, unit-economics, data-cleaning, analyze, duckdb]
6
6
  origin: risco
@@ -51,13 +51,13 @@ When in doubt between two, fit both plus the baseline in one `StatsForecast` run
51
51
 
52
52
  The metrics are not decoration — they decide what you ship.
53
53
 
54
- - **WAPE, not MAPE.** MAPE divides by the actual, so it explodes and misleads whenever actuals approach zero (constant in SKU and intermittent data). WAPE = total absolute error / total actual volume — it weights error by volume and stays stable. Use WAPE as the default magnitude metric.
55
- - **Pair WAPE with bias.** WAPE tells you *how big* the error is; bias tells you the *direction* — whether you systematically over- or under-forecast. A 10% WAPE with +9% bias means you are almost always forecasting high; that is an actionable, different problem than random error.
56
- - **MASE < 1.0 is the pass/fail line.** MASE is scale-free and compares your error to the naive forecast's error. < 1.0 = you beat naive (good). ≥ 1.0 = the naive forecast was better — ship the naive one and stop pretending. This is the single most important number in the readout.
57
- - **Rolling-origin, never a single holdout.** Time-series CV repeats the train/test split across multiple cutoffs (expanding window), giving a far more reliable estimate than one lucky/unlucky split. Use `cross_validation(h=…, n_windows=…)`.
58
- - **Always emit an interval.** A point forecast cannot express uncertainty, and point metrics cannot evaluate a distribution. Report `level=[80]` or `[95]`. The interval is not optional polish — it is half the deliverable.
54
+ - **WAPE, not MAPE.** MAPE divides by the actual, so it explodes and misleads whenever actuals approach zero (constant in SKU and intermittent data). WAPE = total absolute error / total actual volume — volume-weighted and stable. It is the default magnitude metric.
55
+ - **Pair WAPE with bias.** WAPE is *how big* the error is; bias is the *direction* — whether you systematically over- or under-forecast. A 10% WAPE with +9% bias means you are almost always forecasting high, an actionable problem quite different from random error.
56
+ - **MASE < 1.0 is the pass/fail line.** MASE is scale-free: your error over the naive forecast's error. Below 1.0 you beat naive; at or above it, ship the naive forecast instead. The single most important number in the readout.
57
+ - **Rolling-origin, never a single holdout.** Time-series CV repeats the train/test split across multiple cutoffs (expanding window), a far more reliable estimate than one lucky/unlucky split. Use `cross_validation(h=…, n_windows=…)`.
58
+ - **Always emit an interval.** A point forecast cannot express uncertainty, and point metrics cannot evaluate a distribution. Report `level=[80]` or `[95]`. The interval is half the deliverable, not optional polish.
59
59
 
60
- Formulas (WAPE, MASE, bias, pinball, coverage), rolling-origin mechanics, and how to read a backtest table are in `references/accuracy-and-backtesting.md`. Per-method when-to-use and the exact statsforecast one-liner for each are in `references/methods-cheatsheet.md`.
60
+ Formulas (WAPE, MASE, bias, pinball, coverage), rolling-origin mechanics, and how to read a backtest table are in [`references/accuracy-and-backtesting.md`](references/accuracy-and-backtesting.md). Per-method when-to-use and the exact statsforecast one-liner for each are in [`references/methods-cheatsheet.md`](references/methods-cheatsheet.md).
61
61
 
62
62
  ## Minimal pipeline
63
63
 
@@ -116,24 +116,24 @@ out.to_csv("forecast.csv", index=False)
116
116
  - **Structural breaks.** A pricing change, a relaunch, a regime shift. Do not train across the break — train on the post-break segment, even if it is short, or the model averages two different worlds.
117
117
  - **Promotions and outliers.** A promo spike is not baseline demand. Mark promo periods and either model them as a regressor or exclude them from the level estimate; otherwise the forecast inherits a spike that will not recur.
118
118
  - **Granularity.** Forecast at the level you act on. If you must report higher, aggregate the forecasts — and check the aggregate is plausible (this often catches per-SKU nonsense).
119
- - **Hierarchy reconciliation.** When SKU forecasts must sum to a category total, reconcile (bottom-up or MinT). Brief note here; the mechanics belong in `references/methods-cheatsheet.md`.
119
+ - **Hierarchy reconciliation.** When SKU forecasts must sum to a category total, reconcile (bottom-up or MinT). Brief note here; the mechanics belong in [`references/methods-cheatsheet.md`](references/methods-cheatsheet.md).
120
120
 
121
121
  ## Anti-patterns
122
122
 
123
- | Bad | Good | Why |
123
+ | Anti-pattern | Why it bites | Do instead |
124
124
  |---|---|---|
125
- | Report a single point number | Report point + 80/95% interval | A point hides uncertainty the reader needs to plan around. |
126
- | Tune ARIMA orders before any baseline | Compute naive/seasonal-naive first | If you cannot beat the free baseline, the tuning was wasted. |
127
- | Score with MAPE on intermittent demand | Use WAPE + bias | MAPE explodes near zero actuals and lies about accuracy. |
128
- | Single train/test holdout | Rolling-origin CV (`n_windows≥3`) | One split is one sample; CV estimates real out-of-sample error. |
129
- | Fit a model on 8 months of monthly data | SeasonalNaive only under 2 cycles | Too few points; the model overfits and underreports its own error. |
130
- | "The model picked it, so it's right" | State method + MASE vs naive | A forecast you cannot defend is worse than no forecast. |
131
- | Trust SKU forecasts without checking the sum | Sanity-check vs the aggregate | Per-SKU errors compound; the total exposes nonsense fast. |
125
+ | Report a single point number | A point hides uncertainty the reader needs to plan around. | Report point + 80/95% interval |
126
+ | Tune ARIMA orders before any baseline | If you cannot beat the free baseline, the tuning was wasted. | Compute naive/seasonal-naive first |
127
+ | Score with MAPE on intermittent demand | MAPE explodes near zero actuals and lies about accuracy. | Use WAPE + bias |
128
+ | Single train/test holdout | One split is one sample; CV estimates real out-of-sample error. | Rolling-origin CV (`n_windows≥3`) |
129
+ | Fit a model on 8 months of monthly data | Too few points; the model overfits and underreports its own error. | SeasonalNaive only under 2 cycles |
130
+ | "The model picked it, so it's right" | A forecast you cannot defend is worse than no forecast. | State method + MASE vs naive |
131
+ | Trust SKU forecasts without checking the sum | Per-SKU errors compound; the total exposes nonsense fast. | Sanity-check vs the aggregate |
132
132
 
133
133
  ## Handoffs
134
134
 
135
135
  - **`../inventory/SKILL.md`** — feed it the demand number; it sizes reorder points and safety stock. Forecasting produces the demand; it does not size the stock.
136
136
  - **`../financial-model/SKILL.md`** — when the projection is driven by *assumptions and drivers* (pricing, hiring), not history, that is a model, not a forecast.
137
137
  - **`../unit-economics/SKILL.md`** — contribution margin, CAC/LTV, payback. No time series, route there.
138
- - **`data-cleaning`** — dirty input (dupes, missing rows, mixed units) goes here *before* you model.
138
+ - **`../data-cleaning/SKILL.md`** — dirty input (dupes, missing rows, mixed units) goes here *before* you model.
139
139
  - **`../analyze/SKILL.md`** — when the question is "why" or a backward-looking metric/aggregation rather than forward extrapolation.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: game-storytelling
3
- description: "Use when designing a game's STORY as an interactive system: premise, theme and narrative pillars; branching narrative and meaningful choice; dialogue trees with state and flags; quests, objectives and fail states; worldbuilding; environmental and systemic storytelling; and keeping story in harmony with play (avoiding ludonarrative dissonance). Engine-agnostic — it designs the narrative graph, variables and beats, then hands the wiring to the engine skill. Triggers: 'write my game's story/premise', 'branching narrative', 'dialogue system/tree', 'quest structure', 'worldbuilding', 'meaningful choices', 'illusion of choice', 'Ink/Yarn Spinner/Twine/articy narrative', 'story keeps fighting the gameplay'. NOT core mechanics, systems or balance (that's game-design); NOT spatial/level layout or encounter placement (that's level-design); NOT the actual dialogue-node code, save format or plugin wiring inside an engine (that's godot/unity/unreal)."
3
+ description: "Use when a game's story is the work: premise and pillars, branching topology, meaningful choice, dialogue state, quests, environmental storytelling, ludonarrative harmony. Author portable — engine wiring is `godot`/`unity`/`unreal`. NOT the mechanics and economy the story serves (that is `game-design`), NOT level layout (that is `level-design`)."
4
4
  tags: [game, narrative, story, dialogue, quest, branching, worldbuilding]
5
5
  recommends: [game-design, level-design]
6
6
  profiles: [full]
@@ -9,23 +9,11 @@ origin: risco
9
9
 
10
10
  # Game Storytelling — Narrative Design (engine-agnostic)
11
11
 
12
- *Design the story as a system the player operates, not a script they watch. This skill owns the narrative graph — premise, pillars, branches, choices, dialogue state, quests, and the storytelling embedded in the world — and hands the runtime wiring to the engine skill.*
12
+ *Design the story as a system the player operates, not a script they watch. This skill owns the narrative graph — premise, pillars, branches, choices, dialogue state, quests, and the storytelling embedded in the world.*
13
13
 
14
- You produce **design artifacts**: a premise/theme/pillars doc, a branch topology, a state/flag table, dialogue in a portable format (Ink/Yarn/Twee/articy), quest specs, and environmental beats. You do **not** write engine node code, save-serialization, or plugin glue — that is `godot`/`unity`/`unreal`. A mechanic question (what the player *does*, economy, balance) is `game-design`; where things sit in space is `level-design`.
14
+ You produce **design artifacts**: a premise/theme/pillars doc, a branch topology, a state/flag table, dialogue in a portable format (Ink/Yarn/Twee/articy), quest specs, and environmental beats. Story is a **system in service of play**; when you catch yourself designing a great scene the mechanics can't honor, reconcile it (see Ludonarrative harmony) rather than ship the dissonance.
15
15
 
16
- ## Fires on / When NOT
17
-
18
- Use when the request is about: a game's story or premise; branching or non-linear narrative; a dialogue system, tree, or conversation logic; quests, objectives, or mission structure; worldbuilding/lore for a game; meaningful choice vs. the illusion of choice; environmental or systemic storytelling; or story that "fights" the gameplay (ludonarrative dissonance).
19
-
20
- Do NOT use (delegate or decline):
21
-
22
- - Core loop, verbs, systems, progression, economy, difficulty, or balance → **game-design**.
23
- - Spatial layout, encounter placement, sightlines, blockout, pacing *of a space* → **level-design**.
24
- - Implementing the dialogue runner, save/serialize of story state, or wiring Ink/Yarn/articy into a build → the engine skill (**godot/unity/unreal**).
25
- - Prose fiction, a screenplay, or a novel with no interactive/branching structure → general writing.
26
- - Marketing copy, store page, or trailer script → **marketing**.
27
-
28
- Story is a **system in service of play**. When you catch yourself designing a great scene the mechanics can't honor, reconcile it (see Ludonarrative harmony) rather than ship the dissonance.
16
+ Boundaries: **game-design** owns what the player *does* — core loop, verbs, systems, progression, economy, difficulty, balance — and the story serves those verbs; call it when resolving dissonance needs a *mechanic* change, or when designing the conditions for systemic/emergent story. **level-design** owns spatial layout, encounter placement, sightlines, blockout and the pacing *of a space* — the space environmental storytelling lives inside; co-own the set-dressing. **godot / unity / unreal** implement the dialogue runner, quest state, save-serialization of story state, and the Ink/Yarn/articy plugin glue — author portable, they wire it. **marketing** owns the store page, premise pitch and trailer copy (external-facing, not in-game narrative). Prose fiction, a screenplay, or a novel with no interactive/branching structure is general writing, not this skill.
29
17
 
30
18
  ## Premise, theme, and pillars (do this first)
31
19
 
@@ -119,25 +107,18 @@ Deliver story *through the world* so the player assembles it and feels ownership
119
107
  - **VO considerations** *(design-side, not recording — that's audio/engine)* — write for the ear (contractions, short clauses); budget line counts early (VO is expensive and near-frozen once recorded); keep a **stable line ID** on every spoken line; don't splice recorded fragments across variables (gender/number/name concatenation breaks in most languages).
120
108
  - **Localization-readiness** *(so the loc pipeline can do its job)* — externalize all player-facing text to string tables keyed by stable id; **never concatenate** sentences or embed grammar in code (gender/plural/word-order differ per language — use full templated strings with ICU-style placeholders); allow +30–40% text expansion; keep variables as named tokens (`{playerName}`), not positional; leave translator notes per line.
121
109
 
122
- ## Anti-patterns / rationalizations → STOP
110
+ ## Anti-patterns
123
111
 
124
- | Rationalization | Reality / Fix |
112
+ | Anti-pattern | Do instead |
125
113
  | --- | --- |
126
- | "I'll just branch it, players love choices" | Pure trees explode (2^N). Use foldback + gates; reconverge on beats. |
127
- | "This choice feels huge" (but nothing reads it back) | If no later node reads the flag, the choice is noise. Show the consequence or cut it. |
128
- | "Both options lead to the same scene, that's fine" | Only if it's expression, not stakes. Never sell a fake choice as consequential. |
129
- | "The story explains why he's a mass murderer" | Words don't beat verbs. Fix the ludonarrative dissonance, don't narrate around it. |
130
- | "Add an audio log to explain the backstory" | Text-dump is the fallback. Try to *show* it environmentally first. |
131
- | "We'll localize later, just hardcode the strings" | Concatenation and hardcoded text break loc. Externalize to keyed string tables now. |
132
- | "The quest can't be failed, simpler that way" | Sometimes; but soft-locking the game on a missed step is a defect — leave an escape. |
133
- | "Let me wire this Ink file into Unity real quick" | Not this skill. Author portable narrative; hand wiring to the engine skill. |
134
-
135
- ## Related skills
136
-
137
- - **game-design** — the verbs, systems, economy, and balance the story must serve; call it when resolving dissonance needs a *mechanic* change, or when designing systemic/emergent story conditions.
138
- - **level-design** — the spatial layout and encounter flow environmental storytelling lives inside; co-own set-dressing narrative.
139
- - **godot / unity / unreal** — the engine that wires the dialogue runner, quest state, save/serialize, and Ink/Yarn/articy plugins. Author portable; they implement.
140
- - **marketing** — store page, premise pitch, trailer copy (external-facing, not in-game narrative).
114
+ | Branching everything because "players love choices" | Pure trees explode (2^N). Use foldback + gates; reconverge on beats. |
115
+ | A choice that feels huge but no later node reads it back | If no later node reads the flag, the choice is noise. Show the consequence or cut it. |
116
+ | Both options lead to the same scene, and it's sold as a big decision | Fine as expression, not as stakes. Never sell a fake choice as consequential. |
117
+ | Explaining in the story why he's a mass murderer | Words don't beat verbs. Fix the ludonarrative dissonance, don't narrate around it. |
118
+ | Adding an audio log to explain the backstory | Text-dump is the fallback. Try to *show* it environmentally first. |
119
+ | Hardcoding strings, "we'll localize later" | Concatenation and hardcoded text break loc. Externalize to keyed string tables now. |
120
+ | A quest that can't be failed because it's simpler that way | Sometimes right; but soft-locking the game on a missed step is a defect — leave an escape. |
121
+ | Wiring the Ink file into Unity here | Not this skill. Author portable narrative; hand wiring to the engine skill. |
141
122
 
142
123
  ## Checklist
143
124
 
@@ -151,9 +132,3 @@ Deliver story *through the world* so the player assembles it and feels ownership
151
132
  - [ ] Environmental/diegetic delivery preferred over text-dumps and non-diegetic narration where the world can carry it.
152
133
  - [ ] All player-facing text externalized to keyed string tables; no concatenation; variables are named tokens; +30–40% expansion allowed.
153
134
  - [ ] VO lines have stable IDs, are written for the ear, and the script is locked before recording is proposed.
154
-
155
- ## References
156
-
157
- - `references/branching-and-state.md` — topologies + diagrams, meaningful vs. illusory choice, state modeling, and the combinatorial-explosion containment kit.
158
- - `references/dialogue-tools.md` — Ink/Yarn/Twine/articy compared, the four primitives, a "pick one" guide, and the same conversation in three formats.
159
- - `references/environmental-storytelling.md` — show-don't-tell catalog, diegetic vs. non-diegetic delivery, systemic/emergent storytelling and the anecdote factory.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gamedev-shipping
3
- description: "Use when exporting, building, packaging, or publishing a game — per engine (Godot export templates, Unity Build Profiles, Unreal Shipping vs Development) and per platform: desktop (Windows/macOS/Linux; macOS codesign + notarytool notarization), web (the COOP same-origin + COEP require-corp headers threaded SharedArrayBuffer WebAssembly builds need, and that Godot's C#/.NET edition can't export to web), mobile (Android JDK 17 build template, AAB vs APK, release keystore; iOS provisioning). Also store prep (icons/splash, metadata, age ratings, AAB for Play, Mac App Store, Steamworks/SteamPipe, itch.io butler), headless-export CI/CD, build/version numbers, and ship-time size/startup optimization. Triggers: 'export my game', 'build for Steam', 'ship to web/mobile', 'publish to the Play Store', 'notarize my Mac build', 'itch.io upload', 'SharedArrayBuffer is not defined'. NOT for writing gameplay/runtime code (that's the engine skill — godot/unity/unreal) or hosting a normal web app/API/container (→ deployment)."
3
+ description: "Use when exporting, packaging, signing, or publishing a game — export presets per engine, macOS notarization, cross-origin isolation for threaded web builds, Android AAB/keystore, iOS provisioning, store submission (Steam, Play, App Store, itch.io), headless build CI. NOT gameplay code inside the artifact (that is `godot`, `unity`, `unreal`), NOT hosting a web app or container (that is `deployment`)."
4
4
  tags: [export, build, release, packaging, store, steam, itch, notarization, webassembly, aab]
5
5
  recommends: [godot, unity, unreal, deployment]
6
6
  profiles: [full]
@@ -29,21 +29,14 @@ Godot templates·Unity Build Profiles·Unreal Shipping desktop·web·mobile
29
29
  | Android | JDK **17**, target a recent API level | AAB required for Google Play (new apps + updates). APK only for sideload/itch/direct. |
30
30
  | iOS/macOS | Xcode 16+, `notarytool` | `altool` notarization is dead — use `xcrun notarytool`. |
31
31
 
32
- ## When to use / When NOT to use
32
+ ## When NOT to use — and who owns it instead
33
33
 
34
- **Use when:**
35
- - Configuring export templates / build presets / packaging settings for any target.
36
- - Signing & notarizing a desktop build, or debugging Gatekeeper/SmartScreen rejections.
37
- - Fixing a web build that boots to `SharedArrayBuffer is not defined` or a blank canvas.
38
- - Producing an AAB/APK or an iOS archive; wiring keystores/provisioning.
39
- - Store submission prep (icons, metadata, ratings) or uploading to Steam/itch/Play/App Store.
40
- - Automating headless exports in CI, or setting version/build numbers.
41
- - Shrinking build size / startup time before release.
42
-
43
- **NOT for (route elsewhere, say so, stop):**
44
- - Writing gameplay, shaders, netcode, or any runtime logic → the **engine** skill (`godot`/`unity`/`unreal`) or `gamedev-shaders`/`gamedev-multiplayer`. This skill packages code; it does not write it.
45
- - Hosting a normal web app, API, or container (Dockerfile, Coolify, Vercel, VPS) → **`deployment`**. A WebAssembly game is *static files*; only its **headers** are special (below).
46
- - Designing game feel, economy, or narrative → `game-design` / `game-storytelling`.
34
+ | Ask | Owner | Why the line is there |
35
+ | --- | --- | --- |
36
+ | Gameplay, shaders, netcode, physics — any runtime logic | `../godot/SKILL.md`, `../unity/SKILL.md`, `../unreal/SKILL.md`, `../gamedev-shaders/SKILL.md`, `../gamedev-multiplayer/SKILL.md`, `../gamedev-physics/SKILL.md` | This skill packages code, it does not write it. The boundary is the export button. |
37
+ | Hosting a normal web app, API or container (Dockerfile, Coolify, Vercel, VPS) | `../deployment/SKILL.md` | A WebAssembly game is *static files*; only its **headers** are special (below). Borrow its Actions + header-setting patterns. |
38
+ | Game feel, economy, narrative | `../game-design/SKILL.md`, `../game-storytelling/SKILL.md` | Design intent, not packaging. |
39
+ | Signing-key and CI secret handling in general | `../secure-coding/SKILL.md` | The practice this skill assumes for keystores/certs. |
47
40
 
48
41
  ## Decision rules (settle these before touching a build)
49
42
 
@@ -96,7 +89,8 @@ RunUAT BuildCookRun -project="Game.uproject" -platform=Win64 \
96
89
  Android adds `-distribution` for an AAB; iOS requires a Mac + provisioning. Run the platform
97
90
  **Turnkey**/SDK setup once (Android Studio + NDK, or Xcode) or the cook fails.
98
91
 
99
- → full per-engine preset/flag tables: `references/mobile-and-desktop.md` and `references/stores-and-ci.md`.
92
+ → full per-engine preset/flag tables: [references/mobile-and-desktop.md](references/mobile-and-desktop.md)
93
+ and [references/stores-and-ci.md](references/stores-and-ci.md).
100
94
 
101
95
  ## Per-platform
102
96
 
@@ -141,7 +135,8 @@ files are fine. Where to set them:
141
135
  `COEP: require-corp` also means every cross-origin subresource (fonts, analytics, embeds) must
142
136
  send CORP/CORS or it's blocked. **Godot C#/.NET has no web export at all** — use GDScript.
143
137
 
144
- → hosts, exact configs, the service-worker shim, self-test: `references/web-export-headers.md`.
138
+ → per-host configs, the service-worker shim, COEP subresource fallout, a self-test snippet and the
139
+ Godot vs Unity web specifics: [references/web-export-headers.md](references/web-export-headers.md).
145
140
 
146
141
  ### Mobile
147
142
 
@@ -162,7 +157,8 @@ Keep the keystore + passwords out of git (CI secret). `versionCode` must increas
162
157
  then upload to App Store Connect / TestFlight via Xcode Organizer or **Transporter**. `CFBundleVersion`
163
158
  must increase per upload.
164
159
 
165
- → full keystore, Play App Signing, provisioning, TestFlight walkthrough: `references/mobile-and-desktop.md`.
160
+ → full keystore + Play App Signing, provisioning/TestFlight, Windows Authenticode and Linux
161
+ AppImage/Flatpak walkthroughs: [references/mobile-and-desktop.md](references/mobile-and-desktop.md).
166
162
 
167
163
  ## Store prep
168
164
 
@@ -174,7 +170,8 @@ must increase per upload.
174
170
  - **itch.io**: `butler push build/ user/game:channel --userversion 1.2.3` — channel name (e.g. `windows`, `html5`) picks the platform.
175
171
  - **Mac App Store**: Apple Distribution cert + App Sandbox entitlements (not Developer ID); notarization is handled by App Store submission.
176
172
 
177
- → Steamworks/SteamPipe VDF, butler channels, Play/App Store checklists: `references/stores-and-ci.md`.
173
+ → Steamworks/SteamPipe VDF, butler channels, Play/App Store submission checklists:
174
+ [references/stores-and-ci.md](references/stores-and-ci.md).
178
175
 
179
176
  ## CI/CD for builds
180
177
 
@@ -186,7 +183,7 @@ Headless export in GitHub Actions; version from the run/commit so every artifact
186
183
  - **Signing in CI**: import the keystore/cert from an encrypted secret at runtime, never commit it. macOS notarization runs on a `macos-latest` runner with `notarytool` + an App Store Connect API key.
187
184
  - **Versioning**: semver tag for releases; a monotonic build number from `github.run_number` or the git commit count feeds `versionCode`/`CFBundleVersion`/Steam build description.
188
185
 
189
- → ready workflows per engine: `references/stores-and-ci.md`.
186
+ → ready per-engine workflows with signing: [references/stores-and-ci.md](references/stores-and-ci.md).
190
187
 
191
188
  ## Ship-time optimization
192
189
 
@@ -195,26 +192,19 @@ Headless export in GitHub Actions; version from the run/commit so every artifact
195
192
  - **Startup**: small boot scene, stream/preload heavy assets, compress the `.pck`/data, use Ogg Vorbis over WAV. Web: enable gzip/brotli on `.wasm`/`.pck`.
196
193
  - **Budgets**: set a per-platform size budget (web especially — every MB is download latency) and check the final artifact against it before submitting.
197
194
 
198
- ## Anti-patterns — rationalization → STOP
195
+ ## Anti-patterns
199
196
 
200
- | Rationalization | STOP — do this instead |
197
+ | Anti-pattern | Do instead |
201
198
  | --- | --- |
202
- | "Web build works locally, host later" | Set COOP/COEP now; `file://`/simple servers hide the `SharedArrayBuffer` failure. |
203
- | "I'll add C# web export for Godot" | It doesn't exist in 4.x. GDScript for web, or no web. |
204
- | "Notarization is optional" | On macOS, no notarize+staple = Gatekeeper blocks the app for every user. |
205
- | "Ship an APK to the Play Store" | Play requires **AAB** for new apps and updates. |
206
- | "Commit the keystore so CI can sign" | Keystore/cert live in encrypted CI secrets, never in git. |
207
- | "Ship the Development/Debug config" | Ship Godot release / Unity IL2CPP release / Unreal **Shipping** — debug leaks console + is slow. |
208
- | "Templates are close enough (4.5 vs 4.5.1)" | Godot templates must match the editor build exactly or export breaks. |
209
- | "Uncompressed textures are fine" | Per-platform compression (ASTC/BCn/ETC2) — raw textures blow memory + size. |
210
- | "Reuse an old versionCode/CFBundleVersion" | Both must strictly increase or the store rejects the upload. |
211
-
212
- ## Related skills
213
-
214
- - `godot`, `unity`, `unreal` — write the game; this skill exports/ships what they build. Draw the line at the export button.
215
- - `deployment` — Docker/CI/hosting for **web apps & APIs**; borrow its GitHub Actions + header-setting patterns, but a WebAssembly game is static files, not a container.
216
- - `gamedev-shaders`, `gamedev-multiplayer`, `gamedev-physics` — runtime subsystems packaged into the ship artifact, not configured here.
217
- - `secure-coding` — signing-key and secret handling this skill assumes for keystores/certs in CI.
199
+ | Web build works locally, host it later | Set COOP/COEP now; `file://` and simple servers hide the `SharedArrayBuffer` failure. |
200
+ | Planning a Godot C# web export | It doesn't exist in 4.x. GDScript for web, or no web. |
201
+ | Treating notarization as optional | On macOS, no notarize + staple = Gatekeeper blocks the app for every user. |
202
+ | Shipping an APK to the Play Store | Play requires **AAB** for new apps and updates. |
203
+ | Committing the keystore so CI can sign | Keystore/cert live in encrypted CI secrets, never in git. |
204
+ | Shipping the Development/Debug config | Ship Godot release / Unity IL2CPP release / Unreal **Shipping** — debug leaks console + is slow. |
205
+ | Export templates "close enough" (4.5 vs 4.5.1) | Godot templates must match the editor build exactly or export breaks. |
206
+ | Uncompressed textures | Per-platform compression (ASTC/BCn/ETC2) — raw textures blow memory + size. |
207
+ | Reusing an old versionCode/CFBundleVersion | Both must strictly increase or the store rejects the upload. |
218
208
 
219
209
  ## Checklist
220
210
 
@@ -228,9 +218,3 @@ Headless export in GitHub Actions; version from the run/commit so every artifact
228
218
  - [ ] Store assets: icons, splash, screenshots, metadata, age rating done.
229
219
  - [ ] Version/build number set from CI and traceable.
230
220
  - [ ] Textures compressed per platform; build size within budget.
231
-
232
- ## References
233
-
234
- - `references/web-export-headers.md` — cross-origin isolation deep dive: COOP/COEP per host (Netlify/Vercel/nginx/itch/GitHub Pages), the `coi-serviceworker` shim, COEP subresource fallout, self-test snippet, Godot vs Unity web specifics.
235
- - `references/mobile-and-desktop.md` — Android keystore + Gradle template + Play App Signing; iOS provisioning/TestFlight; full macOS codesign→notarytool→staple; Windows Authenticode; Linux AppImage/Flatpak.
236
- - `references/stores-and-ci.md` — Steamworks/SteamPipe VDF upload, itch.io butler channels, Play/App Store submission checklists, and per-engine GitHub Actions headless-build workflows with signing.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: godot
3
- description: "Use when writing, reviewing, or debugging Godot 4.x games in GDScript (typed) or C# — nodes/scenes/custom Resources, autoload singletons and an EventBus, signals via Callable, @onready/@export/@tool, static typing, CharacterBody2D/3D + velocity + move_and_slide(), _process vs _physics_process, .tscn/.tres text formats, and headless GUT/gdUnit4 tests. Enforces Godot 4 APIs and rejects Godot 3 leftovers: yield→await, onready→@onready, .instance()→.instantiate(), KinematicBody→CharacterBody, Spatial→Node3D, string connect(\"sig\",obj,\"m\")→Callable. Triggers: 'write a Godot player controller', 'my move_and_slide does nothing', 'port this Godot 3 script to 4', 'connect a signal in Godot', 'GDScript won't type-check', 'CharacterBody2D won't move', 'add an autoload', 'escribe un script de Godot', 'por qué no se mueve mi personaje'. NOT Unity MonoBehaviour or Unreal (route to unity/unreal); NOT pure C++/CMake tooling unrelated to GDExtension (that is cpp); NOT shader code in .gdshader (that is gamedev-shaders)."
3
+ description: "Use when writing, reviewing, or debugging Godot 4.x games in GDScript or C# — scenes, nodes, custom Resources, autoload/EventBus signals, typed GDScript, CharacterBody2D/3D movement, GUT/gdUnit4 — or porting Godot 3 APIs to 4. NOT Unity/Unreal (that is `unity`/`unreal`), NOT `.gdshader` code (`gamedev-shaders`), NOT GDExtension C++ tooling (`cpp`)."
4
4
  tags: [godot, gdscript, game-dev, csharp, godot4]
5
5
  recommends: [gamedev-shaders, gamedev-multiplayer, gamedev-physics, gamedev-pathing, gamedev-shipping, game-design, cpp]
6
6
  profiles: [full]
@@ -9,9 +9,9 @@ origin: risco
9
9
 
10
10
  # Godot 4.x (GDScript + C#)
11
11
 
12
- Write, review, and debug Godot **4.x** games — 2D and 3D — the way the engine is designed:
13
- scenes as reusable units, composition over deep node trees, signals for decoupling, static
14
- typing for speed and safety. GDScript (typed) is primary; C# parity snippets sit beside it.
12
+ Build 2D and 3D the way the engine is designed: scenes as reusable units, composition over deep node
13
+ trees, signals for decoupling, static typing for speed and safety. GDScript (typed) is primary; C#
14
+ parity snippets sit beside it.
15
15
 
16
16
  ## Version contract — read first
17
17
 
@@ -111,8 +111,11 @@ Keep gameplay logic in nodes; let the bus carry the *notification*, not the beha
111
111
  children in `_init`.
112
112
  - **Prefer unique names**: mark a node **Unique Name in Owner** (`%`) and access `%HealthBar`
113
113
  instead of the fragile, refactor-breaking `get_node("../../UI/HealthBar")`. `$Foo` is fine for a
114
- direct child.
114
+ direct child — `get_node`/`$` on a missing path returns `null` and errors.
115
115
  - Cache node lookups in `@onready` vars; don't call `get_node` every frame.
116
+ - **Freeing**: call `queue_free()` (safe, end of frame), not `free()` mid-signal. Guard reused refs
117
+ with `is_instance_valid(node)`.
118
+ - Never busy-wait; `await get_tree().create_timer(1.0).timeout` or `await` a signal.
116
119
 
117
120
  ```gdscript
118
121
  extends CharacterBody2D
@@ -286,34 +289,12 @@ like any other library. That is native-tooling territory → pair with `cpp`.
286
289
  - Validate a project before shipping: open in the editor once (catches broken `.tscn`/`.tres`),
287
290
  then export-check per platform. Details → `references/export-and-testing.md`.
288
291
 
289
- ## Guardrails / gotchas
290
-
291
- - Freeing: call `queue_free()` (safe, end of frame), not `free()` mid-signal. Guard reused refs with
292
- `is_instance_valid(node)`.
293
- - Never busy-wait; `await get_tree().create_timer(1.0).timeout` or a signal.
294
- - `get_node`/`$` on a missing path returns `null` and errors — prefer `%UniqueName` and typed `@onready`.
295
- - Don't multiply by `delta` twice (see `move_and_slide`). Don't put physics in `_process`.
296
- - One `TileMapLayer` per layer; `TileMap` is deprecated.
297
- - Editor-touching code must guard on `Engine.is_editor_hint()` under `@tool`.
298
-
299
- ## Related skills
300
-
301
- - [`game-design`](../game-design/SKILL.md) — mechanics, loops, and feel *before* you script them.
302
- - [`gamedev-shaders`](../gamedev-shaders/SKILL.md) — `.gdshader` / visual shaders (out of scope here).
303
- - [`gamedev-physics`](../gamedev-physics/SKILL.md) — joints, RigidBody tuning, deep collision layers.
304
- - [`gamedev-pathing`](../gamedev-pathing/SKILL.md) — NavigationAgent, A*, steering beyond the basics.
305
- - [`gamedev-multiplayer`](../gamedev-multiplayer/SKILL.md) — `MultiplayerSynchronizer`/RPC/netcode.
306
- - [`gamedev-shipping`](../gamedev-shipping/SKILL.md) — store builds, signing, platform export at scale.
307
- - [`cpp`](../cpp/SKILL.md) — the GDExtension / `godot-cpp` native side and its CMake/build tooling.
308
-
309
- ## Checklist
310
-
311
- - [ ] Zero Godot 3 APIs — checked every line against the ban-list (`yield`/`onready`/`instance()`/`KinematicBody`/`Spatial`/string `connect`/`File`).
312
- - [ ] `move_and_slide()` called with **no args**; `velocity` set as a property; not multiplied by `delta` twice.
313
- - [ ] Overridden lifecycle methods call `super()` where a base defines them.
314
- - [ ] Signals connected via Callable (`x.sig.connect(_on_x)`), named past-tense, disconnected/one-shot where needed.
315
- - [ ] Everything typed (`:` / `:=`, typed params/returns, typed Arrays); no stray `Variant`.
316
- - [ ] Physics in `_physics_process`, visuals in `_process`; rate-based values scaled by `delta`.
317
- - [ ] Node access via `@onready` + `%UniqueName`, not deep `get_node("../..")` chains.
318
- - [ ] `.tscn`/`.tres` not hand-corrupted; project opens in-editor before export.
319
- - [ ] C# snippets use `partial`, `[Export]`/`[Signal]`, `base._Ready()`, PascalCase (if C# requested).
292
+ ## Hand off to
293
+
294
+ Mechanics, loops, and feel *before* you script them → [`game-design`](../game-design/SKILL.md).
295
+ `.gdshader` / visual shaders → [`gamedev-shaders`](../gamedev-shaders/SKILL.md). Joints, RigidBody
296
+ tuning, deep collision layers → [`gamedev-physics`](../gamedev-physics/SKILL.md). NavigationAgent,
297
+ A*, steering → [`gamedev-pathing`](../gamedev-pathing/SKILL.md). `MultiplayerSynchronizer`/RPC/netcode
298
+ → [`gamedev-multiplayer`](../gamedev-multiplayer/SKILL.md). Store builds, signing, platform export at
299
+ scale → [`gamedev-shipping`](../gamedev-shipping/SKILL.md). The GDExtension / `godot-cpp` native side
300
+ and its CMake/build tooling → [`cpp`](../cpp/SKILL.md).