@ericrisco/rsc 0.1.51 → 0.1.52

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.51",
2
+ "version": "0.1.52",
3
3
  "counts": {
4
4
  "skills": 258
5
5
  },
@@ -1889,7 +1889,7 @@
1889
1889
  },
1890
1890
  {
1891
1891
  "id": "gamedev-multiplayer",
1892
- "description": "Use when adding multiplayer, netcode, or replication to a game — syncing players/state across a network, online co-op or PvP, client-server vs peer-to-peer, server-authoritative design, client-side prediction + server reconciliation, snapshot interpolation, lag compensation, tick/netrate, and per-engine wiring: Godot 4.x MultiplayerSpawner/MultiplayerSynchronizer/@rpc/ENetMultiplayerPeer/set_multiplayer_authority, Unity Netcode for GameObjects (NetworkObject/NetworkBehaviour/NetworkVariable/[Rpc]/ServerRpc/ClientRpc), Unreal Actor replication (Replicated/ReplicatedUsing, Server/Client/NetMulticast RPCs, relevancy). Triggers: 'how do I sync players', 'client and server desync', 'players rubber-band or teleport', 'who has authority', 'laggy movement', 'cheater set their own health'. NOT single-player gameplay, AI, or input (route to engine skill godot/unity/unreal), and NOT matchmaking, dedicated-server hosting, or backend infra (route to deployment).",
1892
+ "description": "Use when adding multiplayer or netcode to a game — client-server vs P2P, server authority and anti-cheat, state replication vs RPCs, prediction and reconciliation, lag compensation, plus Godot 4 / Unity NGO / Unreal wiring. NOT single-player gameplay (that is `godot`, `unity`, `unreal`), NOT matchmaking or server hosting (that is `deployment`).",
1893
1893
  "tags": [
1894
1894
  "multiplayer",
1895
1895
  "netcode",
@@ -1910,7 +1910,7 @@
1910
1910
  },
1911
1911
  {
1912
1912
  "id": "gamedev-pathing",
1913
- "description": "Use when implementing AI navigation or pathfinding in a game - moving enemies/NPCs/units toward goals, \\\"how do enemies navigate the level\\\", A*/Dijkstra/JPS/HPA* search, choosing grid vs waypoint-graph vs navmesh, baking a navmesh and tuning agent radius/height, off-mesh/nav links, dynamic obstacles and re-baking, steering (seek/flee/arrive/pursue/wander/path-following/flocking), local avoidance (RVO/ORCA, crowds), and flow fields for many agents to one goal. Per-engine: Godot 4.x (NavigationServer2D/3D, NavigationRegion, NavigationAgent, get_next_path_position), Unity (NavMeshAgent + NavMeshObstacle + AI Navigation baking), Unreal (RecastNavMesh + AIController + Behavior Trees/EQS). Triggers: \\\"my enemies get stuck\\\", \\\"units clump together\\\", \\\"navmesh not updating\\\", \\\"agentes se atascan\\\". NOT physics/rigidbody collision response or character-controller tuning (gamedev-physics), and NOT high-level enemy AI behaviour design like aggro/states/difficulty (game-design).",
1913
+ "description": "Use when making NPCs, enemies, or units navigate a level — grid vs waypoint vs navmesh, A*/JPS, navmesh baking and agent radius, off-mesh links, steering, RVO crowd avoidance, and flow fields in Godot 4.x, Unity, Unreal. NOT collision response or character controllers (that is gamedev-physics), NOT aggro or difficulty design (that is game-design).",
1914
1914
  "tags": [
1915
1915
  "pathfinding",
1916
1916
  "navmesh",
@@ -4175,7 +4175,7 @@
4175
4175
  },
4176
4176
  {
4177
4177
  "id": "security-scan",
4178
- "description": "Use when running automated security scanners over a repo or app and turning the raw output into a triaged, ranked, gate-able report: scan for vulnerabilities before shipping, audit dependencies/lockfiles for known CVEs, find secrets committed to the tree or git history, run SAST, or wire scanners into CI. Triggers: 'scan this repo for vulnerabilities', 'check my package-lock for CVEs', 'did anyone commit AWS keys', 'scan git history for leaked keys', 'my lockfile has a transitive CVE', 'is aquasecurity/trivy-action@latest safe', 'set up Semgrep/gitleaks to fail CI', 'escanea el repo en busca de vulnerabilidades', 'audita las dependencias', 'analitza les dependències'. NOT threat-modeling, OWASP design reasoning, or authoring the fix (that is secure-coding).",
4178
+ "description": "Use when automated scanners drive a security sweep of a repo or app — SAST, dependency/lockfile CVEs, secrets in the tree or git history, IaC misconfig — and the raw output has to become one deduped, exploitability-ranked report CI can gate on. NOT threat-modeling, OWASP design reasoning, or hand-authoring the fix (that is `secure-coding`).",
4179
4179
  "tags": [
4180
4180
  "security",
4181
4181
  "sast",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ericrisco/rsc",
3
- "version": "0.1.51",
3
+ "version": "0.1.52",
4
4
  "description": "Eric Risco's agent-skills catalog as a granular, self-recommending CLI installer.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gamedev-multiplayer
3
- description: "Use when adding multiplayer, netcode, or replication to a game — syncing players/state across a network, online co-op or PvP, client-server vs peer-to-peer, server-authoritative design, client-side prediction + server reconciliation, snapshot interpolation, lag compensation, tick/netrate, and per-engine wiring: Godot 4.x MultiplayerSpawner/MultiplayerSynchronizer/@rpc/ENetMultiplayerPeer/set_multiplayer_authority, Unity Netcode for GameObjects (NetworkObject/NetworkBehaviour/NetworkVariable/[Rpc]/ServerRpc/ClientRpc), Unreal Actor replication (Replicated/ReplicatedUsing, Server/Client/NetMulticast RPCs, relevancy). Triggers: 'how do I sync players', 'client and server desync', 'players rubber-band or teleport', 'who has authority', 'laggy movement', 'cheater set their own health'. NOT single-player gameplay, AI, or input (route to engine skill godot/unity/unreal), and NOT matchmaking, dedicated-server hosting, or backend infra (route to deployment)."
3
+ description: "Use when adding multiplayer or netcode to a game — client-server vs P2P, server authority and anti-cheat, state replication vs RPCs, prediction and reconciliation, lag compensation, plus Godot 4 / Unity NGO / Unreal wiring. NOT single-player gameplay (that is `godot`, `unity`, `unreal`), NOT matchmaking or server hosting (that is `deployment`)."
4
4
  tags: [multiplayer, netcode, replication, networking, prediction, authority]
5
5
  recommends: [godot, unity, unreal, gamedev-physics]
6
6
  profiles: [full]
@@ -14,6 +14,16 @@ topology, put authority in the right place, replicate the right state, and hide
14
14
  opening the door to cheaters. This skill owns the *networking* decisions; the engine skills own
15
15
  the local gameplay those decisions sit on top of.
16
16
 
17
+ Route elsewhere when the ask is not netcode:
18
+
19
+ | The ask | Route to | Why not here |
20
+ | --- | --- | --- |
21
+ | Single-player movement, AI, input, animation, save files | [`godot`](../godot/SKILL.md) / [`unity`](../unity/SKILL.md) / [`unreal`](../unreal/SKILL.md) | The engine skill owns local gameplay; no network dimension. |
22
+ | Physics determinism, collision, character controllers | [`gamedev-physics`](../gamedev-physics/SKILL.md) | Netcode *consumes* determinism; it does not own the physics fix. |
23
+ | Matchmaking, lobby backend, dedicated-server hosting, relays, DB, game-server CI | [`deployment`](../deployment/SKILL.md) | Running the fleet, not designing the in-game net layer. |
24
+ | Web realtime — chat, presence, a generic WebSocket app | [`webhooks`](../webhooks/SKILL.md) | Not a game world/simulation. |
25
+ | General threat modeling, authz review | [`secure-coding`](../secure-coding/SKILL.md) | This skill keeps only the game-specific anti-cheat controls. |
26
+
17
27
  ## Version contract — read first
18
28
 
19
29
  Target the current APIs. **Never emit these deprecated / removed APIs:**
@@ -30,19 +40,6 @@ community UNet-like fork), say so; this skill targets first-party NGO. In NGO 2.
30
40
  `[ServerRpc]` / `[ClientRpc]` still compile (and enforce `…ServerRpc` / `…ClientRpc` method-name
31
41
  suffixes) — cover them but prefer the unified form on new code.
32
42
 
33
- ## Fires on / When NOT
34
-
35
- **Fires on:** "how do I sync players", replication, netcode, RPCs, authority, online co-op or PvP,
36
- "client and server disagree", rubber-banding / teleporting players, prediction & reconciliation,
37
- lag compensation, tick rate / send rate, spawning networked objects, "the client can cheat".
38
-
39
- **When NOT (route away):**
40
-
41
- - Single-player movement, AI, input, animation, save files → the engine skill: `godot`, `unity`, `unreal`.
42
- - Physics determinism, collision, character controllers → `gamedev-physics` (netcode *consumes* it).
43
- - Matchmaking service, lobby backend, dedicated-server hosting/orchestration, relays, DB → `deployment`.
44
- - Web realtime (chat, presence, generic WebSocket app) that is not a game world → `webhooks` / a backend skill.
45
-
46
43
  ## Topologies & authority
47
44
 
48
45
  Pick the topology first; everything else follows from it.
@@ -61,7 +58,8 @@ requests), never results. **Never trust the client:** the client cannot set its
61
58
  score, currency, or hit results — it *asks*, the server *decides*, everyone else *observes*. A client
62
59
  that says "I moved to X / I did 40 damage / I have 999 gold" is either lagging or cheating; treat both
63
60
  the same. The one thing a client legitimately owns is its own input and, by convention, cosmetic-only
64
- state. See references/prediction-and-latency.md for how to keep this responsive.
61
+ state. See **[references/prediction-and-latency.md](references/prediction-and-latency.md)** for how to
62
+ keep this responsive.
65
63
 
66
64
  ## State replication vs RPCs
67
65
 
@@ -88,7 +86,7 @@ is the #1 cause of "it works for the host but not the client" bugs.
88
86
  ## The hard problems
89
87
 
90
88
  Latency (round-trip time, RTT) is the enemy; jitter and packet loss make it worse. Four techniques,
91
- covered in depth in **references/prediction-and-latency.md**:
89
+ covered in depth in **[references/prediction-and-latency.md](references/prediction-and-latency.md)**:
92
90
 
93
91
  1. **Client-side prediction** — the owning client applies its own input *immediately* instead of waiting a
94
92
  full RTT for the server, so local movement feels instant.
@@ -140,7 +138,8 @@ func request_fire(target: Vector3) -> void:
140
138
  - `MultiplayerSynchronizer` streams a chosen property list (position, etc.) from the authority to peers;
141
139
  set its replication interval and visibility (`set_visibility_for(peer, bool)`) to scope bandwidth.
142
140
  - `MultiplayerSpawner` replicates instancing of scenes under a path so late peers get existing objects.
143
- - Details, prediction wiring, and the full player-scene pattern: **references/godot-high-level-multiplayer.md**.
141
+ - Details, prediction wiring, and the full player-scene pattern:
142
+ **[references/godot-high-level-multiplayer.md](references/godot-high-level-multiplayer.md)**.
144
143
 
145
144
  ### Unity — Netcode for GameObjects
146
145
 
@@ -168,7 +167,8 @@ public class Player : NetworkBehaviour {
168
167
  - `NetworkVariable<T>(value, readPerm, writePerm)` — `NetworkVariableWritePermission.Server` (default) vs
169
168
  `.Owner`; subscribe via `OnValueChanged`. Use `NetworkTransform` for pos/rot sync.
170
169
  - Prefer the unified `[Rpc(SendTo.X)]`; legacy `[ServerRpc]`/`[ClientRpc]` still work but need the
171
- method-name suffixes. Full patterns: **references/unity-and-unreal-netcode.md**.
170
+ method-name suffixes. Full patterns:
171
+ **[references/unity-and-unreal-netcode.md](references/unity-and-unreal-netcode.md)**.
172
172
 
173
173
  ### Unreal — Actor replication
174
174
 
@@ -196,7 +196,8 @@ void AMyPawn::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& Out) const {
196
196
  - **Relevancy** keeps bandwidth sane: `NetCullDistanceSquared`, `bAlwaysRelevant`, `IsNetRelevantFor`, and
197
197
  dormancy (`SetNetDormancy`) stop replicating actors a client can't perceive. Movement replicates via
198
198
  `CharacterMovementComponent`, which already does prediction+reconciliation for you.
199
- - RepNotify vs Multicast, GAS/Network Prediction notes: **references/unity-and-unreal-netcode.md**.
199
+ - RepNotify vs Multicast, GAS/Network Prediction notes:
200
+ **[references/unity-and-unreal-netcode.md](references/unity-and-unreal-netcode.md)**.
200
201
 
201
202
  ## Security / anti-cheat basics
202
203
 
@@ -219,32 +220,18 @@ void AMyPawn::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& Out) const {
219
220
  - Always test **with simulated latency and packet loss**, not just on localhost — localhost hides every
220
221
  prediction/reconciliation bug. Test the client path, not only the host's.
221
222
 
222
- ## Guardrails / gotchas
223
-
224
- - Localhost is a liar: 0 ms RTT masks the exact desync/rubber-band bugs your players will hit. Inject lag.
225
- - Don't RPC state you need to stay consistent — replicate it (an unreliable event drop is permanent).
226
- - Don't tie simulation to render FPS; fixed timestep on the sim, interpolate on the render.
227
- - The listen-server host is a client too — guard authority-only logic behind an `is_server`/`HasAuthority`
228
- check or it double-executes on the host.
229
- - Wrong ownership = "works for host, breaks for client." Set authority/ownership explicitly on spawn.
230
- - Replicating everything, every tick, to everyone melts bandwidth — scope by relevancy/visibility and rate.
231
-
232
- ## Related skills
233
-
234
- - **`godot` / `unity` / `unreal`** — the engine your game runs in; owns local gameplay, input, scenes, build.
235
- - **`gamedev-physics`** — determinism, collision, character controllers; netcode replicates its results and
236
- needs its determinism for prediction/rollback.
237
- - **`deployment`** — dedicated-server hosting, matchmaking/lobby backend, relays, and CI for game servers.
238
- - **`secure-coding`** — general threat modeling; this skill keeps only the game-specific anti-cheat controls.
239
-
240
- ## Checklist
241
-
242
- - [ ] Topology chosen (dedicated / listen / P2P) and the *same code* runs on server and listen host.
243
- - [ ] Server-authoritative: clients send intent only; server validates and owns all gameplay state.
244
- - [ ] Each networked value is either replicated (state/nouns) or an RPC (events/verbs) — not the wrong one.
245
- - [ ] Ownership/authority set explicitly per object; authority-only logic guarded on the host.
246
- - [ ] Owning-client movement predicted + reconciled; remote entities snapshot-interpolated.
247
- - [ ] Hitscan uses server-side lag compensation; simulation on a fixed tick, decoupled from render FPS.
248
- - [ ] Only need-to-know state replicated per client (relevancy/visibility scoped); RPCs rate-limited.
249
- - [ ] Tested with simulated latency + packet loss across multiple instances, exercising the client path.
250
- - [ ] No banned APIs (UNet/HLAPI, Godot 3.x `master`/`puppet`/`rset`, `Tick`-polled Unreal replication).
223
+ ## Anti-patterns
224
+
225
+ | Anti-pattern | Why it bites | Do instead |
226
+ | --- | --- | --- |
227
+ | Writing net code before the topology is chosen | Authority and cost model change everything downstream | Pick dedicated / listen / P2P first, and make the *same code* run on server and listen host |
228
+ | Trusting a client-reported result (health, position, score, hit) | That is the cheat surface, and lag looks identical to cheating | Clients send intent only; the server validates and owns all gameplay state |
229
+ | RPCing state that must stay consistent | A dropped unreliable event desyncs that client permanently | Replicate nouns (state), RPC verbs (events) — replicated values self-correct |
230
+ | Ownership/authority left implicit | The #1 cause of "works for the host, breaks for the client" | Set authority/ownership explicitly on spawn |
231
+ | Forgetting the listen-server host is also a client | Authority-only logic double-executes on the host | Guard it behind `is_server()` / `HasAuthority()` |
232
+ | Making the owning client wait a full RTT for its own input | Movement feels sluggish and unresponsive | Predict locally + reconcile; snapshot-interpolate remote entities |
233
+ | Client-side hit detection for hitscan | Trivially spoofed, and unfair to the higher-ping shooter | Server-side lag compensation: rewind to the shooter's render time |
234
+ | Tying simulation to render FPS | Sim diverges between machines at different frame rates | Fixed timestep on the sim, interpolate on the render |
235
+ | Replicating everything, every tick, to everyone | Melts bandwidth and leaks wallhack fuel | Scope by relevancy/visibility and send rate; rate-limit RPCs |
236
+ | Testing only on localhost | 0 ms RTT masks the exact desync/rubber-band bugs players will hit | Inject latency + packet loss across instances, exercising the client path |
237
+ | Emitting UNet/HLAPI, Godot 3.x `master`/`puppet`/`rset`, or `Tick`-polled Unreal replication | Removed or legacy — it will not compile or will silently underperform | The current APIs in the version contract above |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gamedev-pathing
3
- description: "Use when implementing AI navigation or pathfinding in a game - moving enemies/NPCs/units toward goals, \"how do enemies navigate the level\", A*/Dijkstra/JPS/HPA* search, choosing grid vs waypoint-graph vs navmesh, baking a navmesh and tuning agent radius/height, off-mesh/nav links, dynamic obstacles and re-baking, steering (seek/flee/arrive/pursue/wander/path-following/flocking), local avoidance (RVO/ORCA, crowds), and flow fields for many agents to one goal. Per-engine: Godot 4.x (NavigationServer2D/3D, NavigationRegion, NavigationAgent, get_next_path_position), Unity (NavMeshAgent + NavMeshObstacle + AI Navigation baking), Unreal (RecastNavMesh + AIController + Behavior Trees/EQS). Triggers: \"my enemies get stuck\", \"units clump together\", \"navmesh not updating\", \"agentes se atascan\". NOT physics/rigidbody collision response or character-controller tuning (gamedev-physics), and NOT high-level enemy AI behaviour design like aggro/states/difficulty (game-design)."
3
+ description: "Use when making NPCs, enemies, or units navigate a level — grid vs waypoint vs navmesh, A*/JPS, navmesh baking and agent radius, off-mesh links, steering, RVO crowd avoidance, and flow fields in Godot 4.x, Unity, Unreal. NOT collision response or character controllers (that is gamedev-physics), NOT aggro or difficulty design (that is game-design)."
4
4
  tags: [pathfinding, navmesh, navigation, steering, a-star]
5
5
  recommends: [godot, unity, unreal, gamedev-physics]
6
6
  profiles: [full]
@@ -102,7 +102,8 @@ Combine either as a **weighted sum** (simple) or **priority/arbitration** (avoid
102
102
  **Local avoidance (RVO / ORCA):** each agent picks a velocity that is collision-free assuming neighbours
103
103
  share the burden (*reciprocal* — hence no oscillating "dance"). This is avoidance, **not** collision
104
104
  *response*: it changes intended velocity *before* moving; the physics/collision solver is a separate,
105
- last-resort backstop (→ `gamedev-physics`). For dense crowds use the engine's crowd/avoidance system.
105
+ last-resort backstop (→ [`gamedev-physics`](../gamedev-physics/SKILL.md)). For dense crowds use the
106
+ engine's crowd/avoidance system.
106
107
 
107
108
  **Flow fields** — for **many agents → one (or few) goals** (RTS swarm, tower-defense creeps): run one
108
109
  **Dijkstra from the goal** over the grid to build a cost/integration field, derive a per-cell direction
@@ -182,30 +183,26 @@ AICon->MoveToActor(TargetActor, /*AcceptanceRadius*/ 50.f); // or MoveToLocati
182
183
  4. Costs/holes: **`NavModifierVolume`** + `NavArea` classes. Off-mesh: **`NavLinkProxy`**. Crowd
183
184
  avoidance: enable the **Detour Crowd** manager (or `DetourCrowdAIController`) for RVO on many agents.
184
185
 
185
- > High-level BT *design* (states, aggro, difficulty) is `game-design`; this skill wires the BT's
186
+ > High-level BT *design* (states, aggro, difficulty) is [`game-design`](../game-design/SKILL.md); this skill wires the BT's
186
187
  > movement/EQS tasks to navigation, not the decision tree's semantics.
187
188
 
188
- ## Guardrails / gotchas
189
+ ## Anti-patterns
189
190
 
190
- - **Agent radius mismatch** is the top "stuck in doorways / clipping walls" cause — bake with the real radius.
191
- - Bake covers **static** geometry; runtime-spawned meshes need a rebake, a carving obstacle, or a nav link.
192
- - Path returns empty when start/end are **off the navmesh** or in disconnected islands — snap to nearest poly and check reachability first.
193
- - Avoidance (RVO) ≠ collision (physics). Agents can still overlap under pressure; that is expected, not a physics bug.
194
- - Off-mesh links are **directional and manual** — a jump-down link does not imply a jump-up link.
195
- - Smooth grid paths (funnel / string-pull) or agents walk visible zig-zag staircases.
196
-
197
- ## Anti-patterns / rationalizations → STOP
198
-
199
- | Rationalization | Reality / do instead |
191
+ | Anti-pattern | Do instead |
200
192
  | --- | --- |
201
- | "Just A* every frame, it's fine" | Melts CPU at scale; path on goal-change, steer between frames. |
202
- | "One navmesh bake works for every unit" | Radius/height differ; bake per agent size or use agent-type profiles. |
203
- | "Agents clip through each other — physics bug" | Missing **local avoidance**; enable RVO/crowd, that's the navigation layer. |
204
- | "Navmesh doesn't see my spawned wall" | Static bake; set Dynamic/rebake, or add a carving obstacle/nav link. |
205
- | "I'll grid-search my own A* in Unity/Unreal" | Reinvents the built-in navmesh; use `NavMeshAgent` / `AAIController::MoveTo`. |
206
- | "500 zombies each run A* to the player" | That's a **flow field**: one Dijkstra from the goal, agents sample cells. |
207
- | "Set `agent.destination` and read the path same frame" | Path is async (`pathPending`); gate on it before trusting `remainingDistance`. |
208
- | "Bigger heuristic = smarter" | Over-estimating `h` breaks A* optimality; keep it admissible (or weight it *knowingly*). |
193
+ | Running a full A* every frame | Path on goal-change (or throttled) and steer between frames — per-frame search melts CPU at scale. |
194
+ | One navmesh bake shared by every unit | Radius/height differ; bake per agent size or use agent-type profiles. |
195
+ | Baking with a placeholder agent radius | Bake with the real radius — mismatch is the top "stuck in doorways / clipping walls" cause. |
196
+ | Treating agents that clip through each other as a physics bug | Missing **local avoidance**; enable RVO/crowd — that is the navigation layer. |
197
+ | Expecting RVO to prevent every overlap | Avoidance ≠ collision. Agents can still overlap under pressure; that is expected, not a physics bug. |
198
+ | Expecting a **static** bake to see runtime-spawned geometry | Set Dynamic runtime generation / rebake, or add a carving obstacle or nav link. |
199
+ | Hand-rolling your own grid A* in Unity/Unreal | Reinvents the built-in navmesh; use `NavMeshAgent` / `AAIController::MoveTo`. |
200
+ | 500 zombies each running A* to the player | That's a **flow field**: one Dijkstra from the goal, agents sample cells. |
201
+ | Setting `agent.destination` and reading the path the same frame | Path is async (`pathPending`); gate on it before trusting `remainingDistance`. |
202
+ | Inflating `h` because a bigger heuristic seems smarter | Over-estimating `h` breaks A* optimality; keep it admissible (or weight it *knowingly*). |
203
+ | Trusting a path query that came back empty | Start/end are **off the navmesh** or in disconnected islands — snap to the nearest poly and check reachability first. |
204
+ | Assuming an off-mesh link works both ways | Links are **directional and manual** — a jump-down link does not imply a jump-up link. |
205
+ | Feeding raw grid paths to the mover | Smooth them (funnel / string-pull) or agents walk visible zig-zag staircases. |
209
206
 
210
207
  ## Related skills
211
208
 
@@ -213,7 +210,7 @@ AICon->MoveToActor(TargetActor, /*AcceptanceRadius*/ 50.f); // or MoveToLocati
213
210
  - [`unity`](../unity/SKILL.md) — Unity/C# project setup; here for the NavMesh + AI Navigation package details.
214
211
  - [`unreal`](../unreal/SKILL.md) — UE5/Blueprint/C++; here for RecastNavMesh + AIController/BT/EQS wiring.
215
212
  - [`gamedev-physics`](../gamedev-physics/SKILL.md) — collision *response*, rigidbodies, character controllers; steering decides intended velocity, physics resolves the contact.
216
- - `game-design` — high-level enemy behaviour, aggro, encounter/difficulty design (what the AI *decides*, not how it *moves*).
213
+ - [`game-design`](../game-design/SKILL.md) — high-level enemy behaviour, aggro, encounter/difficulty design (what the AI *decides*, not how it *moves*).
217
214
 
218
215
  ## Checklist
219
216
 
@@ -234,9 +231,3 @@ the project's navigation decisions in `02-DOCS/wiki/stack/gamedev-pathing.md` (i
234
231
  `02-DOCS/wiki/index.md`): engine + version, chosen representation, bake settings (agent sizes, cell
235
232
  size), avoidance/crowd choice, custom links/areas. Read it first on every use; bump its `Updated` date
236
233
  when a convention changes. No `02-DOCS/` layer? Skip silently — conventions are *recorded, not gated*.
237
-
238
- ## See Also — local references (read when)
239
-
240
- - `references/search-algorithms.md` — representations, A*/Dijkstra/JPS/HPA* pseudocode, heuristics & admissibility, tie-breaking, any-angle, funnel smoothing.
241
- - `references/navmesh-workflow.md` — bake-parameter table, areas/costs, off-mesh links, obstacles vs carving vs partial rebake, per-engine baking, debugging.
242
- - `references/steering-and-avoidance.md` — steering primitives, path following, boids weights, RVO/ORCA intuition, crowds, flow-field construction.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: security-scan
3
- description: "Use when running automated security scanners over a repo or app and turning the raw output into a triaged, ranked, gate-able report: scan for vulnerabilities before shipping, audit dependencies/lockfiles for known CVEs, find secrets committed to the tree or git history, run SAST, or wire scanners into CI. Triggers: 'scan this repo for vulnerabilities', 'check my package-lock for CVEs', 'did anyone commit AWS keys', 'scan git history for leaked keys', 'my lockfile has a transitive CVE', 'is aquasecurity/trivy-action@latest safe', 'set up Semgrep/gitleaks to fail CI', 'escanea el repo en busca de vulnerabilidades', 'audita las dependencias', 'analitza les dependències'. NOT threat-modeling, OWASP design reasoning, or authoring the fix (that is secure-coding)."
3
+ description: "Use when automated scanners drive a security sweep of a repo or app — SAST, dependency/lockfile CVEs, secrets in the tree or git history, IaC misconfig — and the raw output has to become one deduped, exploitability-ranked report CI can gate on. NOT threat-modeling, OWASP design reasoning, or hand-authoring the fix (that is `secure-coding`)."
4
4
  tags: [security, sast, sca, secrets, scanning, owasp]
5
5
  recommends: [secure-coding, github-actions, verify]
6
6
  origin: risco
@@ -15,40 +15,28 @@ finding comes from a **tool run**, not a hunch — if you are reasoning about a
15
15
  design or hand-writing a fix, that is [`secure-coding`](../secure-coding/SKILL.md),
16
16
  not this skill.
17
17
 
18
- Your job is orchestration + triage. Not eyeballing code, not authoring patches.
19
-
20
- ## Operating posture
21
-
22
- - **Read-only by default.** Scan, triage, report. Apply fixes (version bumps,
23
- rotation, `.gitignore` edits) only when the user asks. *Why:* a security sweep
24
- that silently mutates the tree destroys the evidence and the trust.
25
- - **Machine-first.** Every finding must trace to a scanner run with a `ruleId`
26
- and a source location. *Why:* "I think this looks injectable" is design
27
- reasoning — route it to `secure-coding`. This skill ships reproducible output.
28
- - **Pin and verify your scanners.** Pin exact versions, verify checksums/SHAs,
29
- never pull `@latest` GitHub Actions. *Why:* in **March 2026 Trivy was
30
- supply-chain compromised** — malicious releases `v0.69.4/0.69.5/0.69.6` and a
31
- hijacked `aquasecurity/trivy-action` exfiltrated CI secrets. Your scanner runs
32
- with repo + CI-secret access; an unpinned scanner is itself the attack surface.
33
- - **SARIF everything.** Make every tool emit SARIF (or JSON you normalize to it).
34
- *Why:* a common schema is what lets you merge four tools, dedupe, and feed one
35
- artifact into CI instead of four incompatible logs.
36
- - **Triage before you report.** Raw scanner output is high-noise. Rank by
37
- exploitability and dedupe overlap; never dump 400 raw findings on the user.
38
-
39
- ## The four scan classes
40
-
41
- | Class | What it catches | Primary tool | Backup / fast pass |
42
- |---|---|---|---|
43
- | **SAST** | injection, XSS, path traversal in *first-party* code | Semgrep | — |
44
- | **SCA / deps** | known CVEs in dependency manifests + lockfiles | osv-scanner | `npm audit`, `pip-audit` |
45
- | **Secrets** | credentials in the tree **or git history** | gitleaks (speed) | TruffleHog (depth + live verification) |
46
- | **Misconfig / IaC** | Dockerfile, k8s, Terraform, exposed config | Trivy `config` | Semgrep rulesets |
47
-
48
- ### Tool selection by ecosystem
49
-
50
- Pick by what is in the repo. This is the real branch point — match the tool to
51
- the manifest, do not run everything everywhere.
18
+ Your job is orchestration + triage: every finding traces to a scanner run with a
19
+ `ruleId` and a source location, so the output is reproducible. Not eyeballing
20
+ code, not authoring patches.
21
+
22
+ **Read-only by default.** Scan, triage, report. Apply fixes (version bumps,
23
+ rotation, `.gitignore` edits) only when the user asks — a security sweep that
24
+ silently mutates the tree destroys the evidence and the trust.
25
+
26
+ **Pin and verify your scanners.** Exact versions, verified checksums/SHAs, never
27
+ `@latest` GitHub Actions. In **March 2026 Trivy was supply-chain compromised** —
28
+ malicious releases `v0.69.4/0.69.5/0.69.6` and a hijacked
29
+ `aquasecurity/trivy-action` exfiltrated CI secrets. Your scanner runs with repo +
30
+ CI-secret access; an unpinned scanner is itself the attack surface.
31
+
32
+ ## Scan classes and tool selection
33
+
34
+ Four classes: **SAST** (injection, XSS, path traversal in *first-party* code),
35
+ **SCA / deps** (known CVEs in dependency manifests + lockfiles), **Secrets**
36
+ (credentials in the tree **or git history**), **Misconfig / IaC** (Dockerfile,
37
+ k8s, Terraform, exposed config). Pick tools by what is in the repo. This is the
38
+ real branch point — match the tool to the manifest, do not run everything
39
+ everywhere.
52
40
 
53
41
  | Repo contains | SAST | SCA | Secrets | Misconfig |
54
42
  |---|---|---|---|---|
@@ -56,15 +44,17 @@ the manifest, do not run everything everywhere.
56
44
  | Python (`poetry.lock`/`requirements.txt`) | Semgrep | osv-scanner + `pip-audit` (fast) | gitleaks → TruffleHog | Trivy |
57
45
  | Go (`go.mod`/`go.sum`) | Semgrep | osv-scanner (+ `govulncheck` for reachability) | gitleaks | Trivy |
58
46
  | Containers (`Dockerfile`, images) | — | Trivy `fs`/`image` | Trivy `--scanners secret` | Trivy `config` |
59
- | IaC (Terraform/k8s/Helm) | Semgrep (IaC rules) | — | gitleaks | Trivy `config` |
47
+ | IaC (Terraform/k8s/Helm) | Semgrep (IaC rules) | — | gitleaks | Trivy `config`, Semgrep rulesets |
60
48
  | Monorepo (mixed) | Semgrep `auto` | osv-scanner (multi-ecosystem) | gitleaks → TruffleHog | Trivy |
61
49
 
62
50
  Full install (pinned), flag matrix, and suppression syntax: `references/tools.md`.
63
51
 
64
52
  ## Run recipes
65
53
 
66
- All recipes emit SARIF or JSON so they merge into one report. **Pin the version
67
- shown** — the placeholders below mark where to lock an exact tag/digest.
54
+ All recipes emit SARIF (or JSON you normalize to it) — a common schema is what
55
+ lets you merge four tools, dedupe, and feed one artifact into CI instead of four
56
+ incompatible logs. **Pin the version shown**; the placeholders below mark where
57
+ to lock an exact tag/digest.
68
58
 
69
59
  ### SAST — Semgrep
70
60
 
@@ -107,10 +97,10 @@ gitleaks detect --redact --report-format sarif --report-path secrets.sarif
107
97
  trufflehog git file://. --only-verified --json > trufflehog.json
108
98
  ```
109
99
 
110
- ### Misconfig / IaC — Trivy (PINNED — see the caveat)
100
+ ### Misconfig / IaC — Trivy (PINNED — see the caveat above)
111
101
 
112
102
  Trivy scans filesystems, images, and IaC and finds transitive CVEs `npm audit`
113
- misses. After the March 2026 compromise, **never** run an unpinned Trivy.
103
+ misses.
114
104
 
115
105
  ```bash
116
106
  # Pin the EXACT version (NOT v0.69.4/.5/.6 — those were the malicious releases).
@@ -200,17 +190,17 @@ Emit one `security-scan-report.json` — the machine-checkable contract CI gates
200
190
 
201
191
  ## Anti-patterns
202
192
 
203
- | Rationalization | Reality |
193
+ | Anti-pattern | Do instead |
204
194
  |---|---|
205
- | "Pull `aquasecurity/trivy-action@latest`, it's official." | March 2026: a hijacked tag stole CI secrets. Pin a full SHA, verify provenance. |
206
- | "Every scanner finding is a bug to fix." | Most are noise. Rank by reachable + exposed + sensitive sink; report the few that matter. |
207
- | "Scanned the working tree, no secrets." | History holds the deleted keys. Scan git history; a removed-in-HEAD key is still leaked and live. |
208
- | "`npm audit` is clean, deps are fine." | Native auditors miss transitive CVEs. Run osv-scanner/Trivy too; native is the fast pass, not the only pass. |
209
- | "Commit a blanket `.semgrepignore` to quiet CI." | A blanket ignore hides the next real bug. Suppress per-finding with a written justification + expiry. |
210
- | "We found a verified key, I deleted it from the file." | Deleting ≠ safe. Rotate the credential first, then scrub history. The committed value is already compromised. |
211
- | "Trust the SARIF `level`, that's the severity." | Tools disagree. Normalize to one scale before you rank or gate. |
212
- | "Dump all four tool outputs in the PR, let the reviewer sort it." | The reviewer won't. Merge, dedupe, rank, and emit one report. |
213
- | "Run the scan; it'll auto-fix the deps." | Read-only by default. Propose bumps; apply only when asked — never mutate during a sweep. |
195
+ | Pulling `aquasecurity/trivy-action@latest` because it is the official action | March 2026: a hijacked tag stole CI secrets. Pin a full SHA, verify provenance. |
196
+ | Treating every scanner finding as a bug to fix | Most are noise. Rank by reachable + exposed + sensitive sink; report the few that matter. |
197
+ | Calling the repo clean after scanning only the working tree | History holds the deleted keys. Scan git history; a removed-in-HEAD key is still leaked and live. |
198
+ | Declaring deps fine because `npm audit` is clean | Native auditors miss transitive CVEs. Run osv-scanner/Trivy too; native is the fast pass, not the only pass. |
199
+ | Committing a blanket `.semgrepignore` to quiet CI | A blanket ignore hides the next real bug. Suppress per-finding with a written justification + expiry. |
200
+ | Deleting a verified key from the file and moving on | Deleting ≠ safe. Rotate the credential first, then scrub history. The committed value is already compromised. |
201
+ | Taking the SARIF `level` as the severity | Tools disagree. Normalize to one scale before you rank or gate. |
202
+ | Dumping all four tool outputs in the PR for the reviewer to sort | The reviewer won't. Merge, dedupe, rank, and emit one report. |
203
+ | Letting the scan auto-fix the deps it finds | Read-only by default. Propose bumps; apply only when asked — never mutate during a sweep. |
214
204
 
215
205
  ## Project grounding (02-DOCS + CLAUDE.md)
216
206
 
@@ -218,23 +208,12 @@ In a project with a `02-DOCS/` layer (the [`harness`](../harness/SKILL.md)
218
208
  Karpathy wiki), record the scanner choices, pinned versions, gate thresholds, and
219
209
  any accepted-risk suppressions in `02-DOCS/wiki/stack/security-scan.md`, and index
220
210
  it in `02-DOCS/wiki/index.md` (the Knowledge map; root `CLAUDE.md` keeps only a short
221
- pointer to it). Read it first on every run so the
222
- next agent inherits the pinned tools and thresholds instead of re-deriving them.
223
- No `02-DOCS/`? Skip silently. Conventions are recorded, not gated — never block
224
- the scan on this.
211
+ pointer to it). Read it first on every run so the next agent inherits the pinned
212
+ tools and thresholds instead of re-deriving them. No `02-DOCS/`? Skip silently.
213
+ Conventions are recorded, not gated — never block the scan on this.
225
214
 
226
215
  ## See Also
227
216
 
228
- - [`secure-coding`](../secure-coding/SKILL.md) — the human-reasoning sibling:
229
- threat-model a feature, hand-write the vulnerable→fixed diff. *If the answer
230
- comes from a tool run it's this skill; if it comes from reasoning about the
231
- design it's secure-coding.*
232
- - [`review`](../review/SKILL.md) — adversarial review of a diff against a spec.
233
- - [`code-review`](../code-review/SKILL.md) — general correctness/quality review.
234
- - [`verify`](../verify/SKILL.md) — the broader lint/type/test green gate this
235
- feeds into.
236
- - **References** — `references/tools.md` (pinned installs, flag matrix,
237
- suppression syntax); `references/triage.md` (ranking rubric, dedupe keying,
238
- severity map, full report schema).
239
- </content>
240
- </invoke>
217
+ Reviewing a diff rather than scanning a repo: [`code-review`](../code-review/SKILL.md)
218
+ for correctness and quality, [`review`](../review/SKILL.md) for adversarial review
219
+ against a spec.
@@ -95,4 +95,3 @@ trivy image --format sarif --output trivy-img.sarif <pinned-image@sha256:...>
95
95
  - Every recipe emits SARIF 2.1.0 so findings merge into one report. Where a tool
96
96
  only emits native JSON (`npm audit`, `pip-audit`, TruffleHog), normalize it to
97
97
  the report schema in `triage.md` rather than gating on its raw shape.
98
- </content>
@@ -90,4 +90,3 @@ This is the contract `scripts/verify.sh` gates on.
90
90
  - **Gate:** any `findings[]` with `status: "open"` and `severity: "critical"`
91
91
  → fail. Strict mode also fails on `open` + `high`. `suppressed`/`fixed` never
92
92
  fail. An empty/clean report exits `0`.
93
- </content>