@ericrisco/rsc 0.1.34 → 0.1.36
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/README.md +28 -2
- package/manifest.json +241 -2
- package/package.json +1 -1
- package/scripts/lib/domains.js +1 -0
- package/scripts/lib/recommend.js +4 -0
- package/skills/agent-eval/SKILL.md +1 -1
- package/skills/analyze/SKILL.md +1 -1
- package/skills/brand-voice/SKILL.md +1 -1
- package/skills/brand-voice/references/voice-guide-template.md +14 -0
- package/skills/building-agents/SKILL.md +2 -2
- package/skills/competitor-watch/SKILL.md +9 -4
- package/skills/competitor-watch/references/tracker-schema.md +19 -0
- package/skills/constitution/references/constitution-template.md +10 -0
- package/skills/content-engine/SKILL.md +1 -1
- package/skills/content-engine/references/brief-and-pipeline.md +15 -1
- package/skills/course-builder/references/grounding-and-scoping.md +23 -0
- package/skills/course-storytelling/references/learner-grounding.md +22 -2
- package/skills/decision-records/SKILL.md +14 -1
- package/skills/decision-records/references/templates.md +20 -0
- package/skills/design/references/brand-grounding.md +11 -1
- package/skills/game-design/SKILL.md +170 -0
- package/skills/game-design/evals/README.md +13 -0
- package/skills/game-design/evals/cases.yaml +47 -0
- package/skills/game-design/references/mechanics-and-loops.md +78 -0
- package/skills/game-design/references/playtesting-and-scope.md +58 -0
- package/skills/game-design/references/progression-and-economy.md +70 -0
- package/skills/game-storytelling/SKILL.md +159 -0
- package/skills/game-storytelling/evals/README.md +28 -0
- package/skills/game-storytelling/evals/cases.yaml +51 -0
- package/skills/game-storytelling/references/branching-and-state.md +134 -0
- package/skills/game-storytelling/references/dialogue-tools.md +117 -0
- package/skills/game-storytelling/references/environmental-storytelling.md +71 -0
- package/skills/gamedev-multiplayer/SKILL.md +250 -0
- package/skills/gamedev-multiplayer/evals/README.md +12 -0
- package/skills/gamedev-multiplayer/evals/cases.yaml +44 -0
- package/skills/gamedev-multiplayer/references/godot-high-level-multiplayer.md +133 -0
- package/skills/gamedev-multiplayer/references/prediction-and-latency.md +104 -0
- package/skills/gamedev-multiplayer/references/unity-and-unreal-netcode.md +166 -0
- package/skills/gamedev-pathing/SKILL.md +242 -0
- package/skills/gamedev-pathing/evals/README.md +14 -0
- package/skills/gamedev-pathing/evals/cases.yaml +49 -0
- package/skills/gamedev-pathing/references/navmesh-workflow.md +110 -0
- package/skills/gamedev-pathing/references/search-algorithms.md +135 -0
- package/skills/gamedev-pathing/references/steering-and-avoidance.md +120 -0
- package/skills/gamedev-physics/SKILL.md +225 -0
- package/skills/gamedev-physics/evals/README.md +12 -0
- package/skills/gamedev-physics/evals/cases.yaml +54 -0
- package/skills/gamedev-physics/references/character-controllers.md +120 -0
- package/skills/gamedev-physics/references/determinism-and-queries.md +124 -0
- package/skills/gamedev-physics/references/layers-and-masks.md +115 -0
- package/skills/gamedev-shaders/SKILL.md +252 -0
- package/skills/gamedev-shaders/evals/README.md +14 -0
- package/skills/gamedev-shaders/evals/cases.yaml +45 -0
- package/skills/gamedev-shaders/references/effect-recipes.md +205 -0
- package/skills/gamedev-shaders/references/godot-shading-language.md +133 -0
- package/skills/gamedev-shaders/references/unity-and-unreal-shaders.md +169 -0
- package/skills/gamedev-shipping/SKILL.md +236 -0
- package/skills/gamedev-shipping/evals/README.md +9 -0
- package/skills/gamedev-shipping/evals/cases.yaml +55 -0
- package/skills/gamedev-shipping/references/mobile-and-desktop.md +127 -0
- package/skills/gamedev-shipping/references/stores-and-ci.md +162 -0
- package/skills/gamedev-shipping/references/web-export-headers.md +140 -0
- package/skills/godot/SKILL.md +319 -0
- package/skills/godot/evals/README.md +13 -0
- package/skills/godot/evals/cases.yaml +50 -0
- package/skills/godot/references/export-and-testing.md +102 -0
- package/skills/godot/references/gdscript-style.md +84 -0
- package/skills/godot/references/godot3-to-4-traps.md +89 -0
- package/skills/godot/references/nodes-scenes-resources.md +109 -0
- package/skills/harness/SKILL.md +3 -3
- package/skills/harness/references/daily-curation-automation.md +8 -6
- package/skills/harness/references/obsidian-scaffolding.md +16 -9
- package/skills/harness/references/wiki-article-template.md +31 -14
- package/skills/harness/references/wiki-index-template.md +7 -3
- package/skills/harness/references/wiki-protocol.md +120 -54
- package/skills/harness/references/wiki-worklog-template.md +5 -1
- package/skills/instagram-api/SKILL.md +8 -1
- package/skills/instagram-api/references/insights-metrics.md +8 -1
- package/skills/knowledge-ops/SKILL.md +9 -9
- package/skills/knowledge-ops/evals/cases.yaml +1 -1
- package/skills/knowledge-ops/references/gardening-playbook.md +18 -8
- package/skills/level-design/SKILL.md +175 -0
- package/skills/level-design/evals/README.md +35 -0
- package/skills/level-design/evals/cases.yaml +58 -0
- package/skills/level-design/references/blockout-to-art.md +118 -0
- package/skills/level-design/references/guidance-and-readability.md +152 -0
- package/skills/level-design/references/pacing-and-encounters.md +142 -0
- package/skills/linkedin-api/SKILL.md +10 -1
- package/skills/linkedin-strategy/SKILL.md +12 -0
- package/skills/linkedin-strategy/references/wiki-records.md +27 -1
- package/skills/marketing/references/brand-grounding.md +22 -2
- package/skills/medium-strategy/SKILL.md +12 -0
- package/skills/medium-strategy/references/wiki-records.md +39 -1
- package/skills/medium-writing/SKILL.md +19 -0
- package/skills/plan/references/plan-template.md +12 -1
- package/skills/roast-me/tools/adapters/__pycache__/__init__.cpython-312.pyc +0 -0
- package/skills/roast-me/tools/adapters/__pycache__/base.cpython-312.pyc +0 -0
- package/skills/roast-me/tools/adapters/__pycache__/claude.cpython-312.pyc +0 -0
- package/skills/roast-me/tools/adapters/__pycache__/codex.cpython-312.pyc +0 -0
- package/skills/roast-me/tools/adapters/__pycache__/gemini.cpython-312.pyc +0 -0
- package/skills/roast-me/tools/adapters/__pycache__/registry.cpython-312.pyc +0 -0
- package/skills/shortform-packaging/SKILL.md +7 -2
- package/skills/shortform-packaging/references/package-templates.md +13 -2
- package/skills/shortform-strategy/SKILL.md +30 -6
- package/skills/shortform-strategy/references/learning-loop-template.md +9 -1
- package/skills/specify/references/spec-template.md +12 -1
- package/skills/tiktok-api/SKILL.md +6 -2
- package/skills/tiktok-api/references/wiki-schema.md +38 -4
- package/skills/unity/SKILL.md +282 -0
- package/skills/unity/evals/README.md +8 -0
- package/skills/unity/evals/cases.yaml +43 -0
- package/skills/unity/references/build-and-platforms.md +65 -0
- package/skills/unity/references/input-system.md +102 -0
- package/skills/unity/references/lifecycle-deep-dive.md +75 -0
- package/skills/unreal/SKILL.md +270 -0
- package/skills/unreal/evals/README.md +12 -0
- package/skills/unreal/evals/cases.yaml +45 -0
- package/skills/unreal/references/blueprint-cpp-parity.md +109 -0
- package/skills/unreal/references/gameplay-framework.md +95 -0
- package/skills/unreal/references/packaging.md +83 -0
- package/skills/verify/SKILL.md +11 -1
- package/skills/youtube-api/SKILL.md +7 -2
- package/skills/youtube-api/references/wiki-schema.md +25 -4
- package/skills/youtube-packaging/SKILL.md +10 -2
- package/skills/youtube-packaging/references/description-and-chapters.md +70 -2
- package/skills/youtube-strategy/SKILL.md +9 -2
- package/skills/youtube-strategy/references/wiki-records.md +39 -6
- package/skills/youtube-strategy/scripts/verify.sh +4 -0
- package/skills/youtube-thumbnails/SKILL.md +10 -5
- package/skills/youtube-thumbnails/references/experiment-log-format.md +28 -2
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# GDScript style & formatting cheat-sheet (Godot 4.x)
|
|
2
|
+
|
|
3
|
+
Mirrors the official GDScript style guide. When in doubt, run the editor's built-in formatter
|
|
4
|
+
(Ctrl/Cmd+Shift+I) and `gdformat` (from `gdtoolkit`) in CI.
|
|
5
|
+
|
|
6
|
+
## Naming
|
|
7
|
+
|
|
8
|
+
| Thing | Case | Example |
|
|
9
|
+
| --- | --- | --- |
|
|
10
|
+
| File (script/scene) | `snake_case` | `player_controller.gd`, `main_menu.tscn` |
|
|
11
|
+
| `class_name` / type | `PascalCase` | `class_name EnemyStats` |
|
|
12
|
+
| Node name in tree | `PascalCase` | `HealthBar`, `AttackTimer` |
|
|
13
|
+
| Variable / function | `snake_case` | `var max_health`, `func take_damage()` |
|
|
14
|
+
| Signal | `snake_case`, past tense | `signal health_depleted` |
|
|
15
|
+
| Constant | `CONSTANT_CASE` | `const MAX_SPEED := 400.0` |
|
|
16
|
+
| Enum type / members | `PascalCase` / `CONSTANT_CASE` | `enum State { IDLE, RUN }` |
|
|
17
|
+
| Private (convention) | leading underscore | `var _internal_timer` |
|
|
18
|
+
| Virtual/lifecycle | leading underscore | `_ready`, `_process`, `_on_body_entered` |
|
|
19
|
+
|
|
20
|
+
## Formatting
|
|
21
|
+
|
|
22
|
+
- **Tabs** for indentation (not spaces). Editor default.
|
|
23
|
+
- Lines **< 100 columns**.
|
|
24
|
+
- One space around binary operators (`a + b`, `x := 1`), none inside call parens.
|
|
25
|
+
- Two blank lines between functions at top level; one inside classes as needed.
|
|
26
|
+
- Prefer `:=` (inferred) when the RHS makes the type obvious; `: Type =` when it does not.
|
|
27
|
+
|
|
28
|
+
## Typed by default
|
|
29
|
+
|
|
30
|
+
```gdscript
|
|
31
|
+
var speed: float = 300.0 # explicit annotation
|
|
32
|
+
var dir := Vector2.ZERO # inferred
|
|
33
|
+
var slots: Array[Item] = [] # typed collection
|
|
34
|
+
const GRAVITY := 980.0
|
|
35
|
+
|
|
36
|
+
func heal(amount: int) -> void: # typed params AND return
|
|
37
|
+
_health = mini(_health + amount, _max_health)
|
|
38
|
+
|
|
39
|
+
func find_target() -> Node2D: # return type declared
|
|
40
|
+
return get_tree().get_first_node_in_group("player")
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- Declare `-> void` on functions that return nothing; declare the real type otherwise.
|
|
44
|
+
- Use `as` for safe downcasts: `var e := body as Enemy` → `null` on mismatch (no crash).
|
|
45
|
+
- Avoid untyped `var x` and `Variant` params — they disable the compiler's checks and the VM's
|
|
46
|
+
typed fast paths.
|
|
47
|
+
|
|
48
|
+
## Script layout order (recommended top-to-bottom)
|
|
49
|
+
|
|
50
|
+
1. `@tool` (if any) — must be the very first line.
|
|
51
|
+
2. `class_name` then `extends` (or `extends` alone).
|
|
52
|
+
3. `## docstring` comment.
|
|
53
|
+
4. `signal` declarations.
|
|
54
|
+
5. `enum` / `const`.
|
|
55
|
+
6. `@export` vars, then plain member vars, then `@onready` vars.
|
|
56
|
+
7. Built-in virtuals: `_init`, `_ready`, `_process`, `_physics_process`, `_input`, …
|
|
57
|
+
8. Public methods, then private (`_underscore`) methods, then signal handlers (`_on_*`).
|
|
58
|
+
|
|
59
|
+
```gdscript
|
|
60
|
+
@tool
|
|
61
|
+
class_name Turret extends Node2D
|
|
62
|
+
## Auto-aiming turret; @export the fire rate in the inspector.
|
|
63
|
+
|
|
64
|
+
signal fired(at: Vector2)
|
|
65
|
+
|
|
66
|
+
const MAX_RANGE := 600.0
|
|
67
|
+
enum Mode { IDLE, TRACKING }
|
|
68
|
+
|
|
69
|
+
@export var fire_rate := 2.0
|
|
70
|
+
var _cooldown := 0.0
|
|
71
|
+
@onready var muzzle: Marker2D = %Muzzle
|
|
72
|
+
|
|
73
|
+
func _physics_process(delta: float) -> void:
|
|
74
|
+
_cooldown = maxf(_cooldown - delta, 0.0)
|
|
75
|
+
|
|
76
|
+
func _on_area_entered(_area: Area2D) -> void:
|
|
77
|
+
pass
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Common built-in math helpers (Godot 4 names)
|
|
81
|
+
|
|
82
|
+
`absf/absi`, `minf/mini`, `maxf/maxi`, `clampf/clampi`, `snappedf`, `lerpf`, `move_toward`,
|
|
83
|
+
`deg_to_rad` / `rad_to_deg`, `randf_range`, `randi_range`. The unsuffixed `abs/min/max/clamp` still
|
|
84
|
+
work on Variants but the typed suffixed forms are faster and clearer.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Godot 3 → 4.x migration ban-list (full table)
|
|
2
|
+
|
|
3
|
+
Godot 4 is a hard break from 3.x. The engine ships a project converter, but it does **not** catch
|
|
4
|
+
everything — and an agent generating fresh code must simply never emit the left column. Use this as
|
|
5
|
+
the authoritative reference when porting or reviewing.
|
|
6
|
+
|
|
7
|
+
## Won't-parse renames (hard errors)
|
|
8
|
+
|
|
9
|
+
| Godot 3 | Godot 4.x | Note |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| `yield(obj, "signal")` | `await obj.signal` | Coroutines are now `await`; the function must not need `yield`'s return-value trick. |
|
|
12
|
+
| `yield(get_tree().create_timer(1),"timeout")` | `await get_tree().create_timer(1.0).timeout` | |
|
|
13
|
+
| `onready var` | `@onready var` | Annotation. |
|
|
14
|
+
| `export var` / `export(int) var` | `@export var` / `@export_range(...) var` | Typed annotations replace the `export(Type)` hint syntax. |
|
|
15
|
+
| `tool` | `@tool` | Must be the first line. |
|
|
16
|
+
| `remote`/`master`/`puppet func` | `@rpc(...)` annotations | Networking model changed entirely. |
|
|
17
|
+
| `setget set_fn, get_fn` | `set(v): ...` / `get: ...` inline accessors | |
|
|
18
|
+
|
|
19
|
+
## Node / class renames
|
|
20
|
+
|
|
21
|
+
| Godot 3 | Godot 4.x |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| `Spatial` | `Node3D` |
|
|
24
|
+
| `KinematicBody` / `KinematicBody2D` | `CharacterBody3D` / `CharacterBody2D` |
|
|
25
|
+
| `Area` | `Area3D` |
|
|
26
|
+
| `RigidBody` / `StaticBody` | `RigidBody3D` / `StaticBody3D` |
|
|
27
|
+
| `Sprite` | `Sprite2D` |
|
|
28
|
+
| `Sprite3D` | `Sprite3D` (unchanged) |
|
|
29
|
+
| `AnimatedSprite` | `AnimatedSprite2D` |
|
|
30
|
+
| `CollisionShape` | `CollisionShape3D` |
|
|
31
|
+
| `Camera` | `Camera3D` |
|
|
32
|
+
| `Light2D` (old) / `Light` | `PointLight2D` / `DirectionalLight2D` / `OmniLight3D` etc. |
|
|
33
|
+
| `Viewport` (as node) | `SubViewport` (embedded) |
|
|
34
|
+
| `YSort` (node) | `y_sort_enabled` property on `Node2D`/`CanvasItem` |
|
|
35
|
+
| `ARVROrigin` / `ARVRCamera` | `XROrigin3D` / `XRCamera3D` |
|
|
36
|
+
| `Reference` | `RefCounted` |
|
|
37
|
+
| `TileMap` | `TileMapLayer` (one per layer; `TileMap` deprecated 4.3+) |
|
|
38
|
+
|
|
39
|
+
## Method / API changes
|
|
40
|
+
|
|
41
|
+
| Godot 3 | Godot 4.x |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| `scene.instance()` | `scene.instantiate()` |
|
|
44
|
+
| `move_and_slide(velocity, up_direction)` | set `velocity` property → `move_and_slide()` (no args) |
|
|
45
|
+
| `move_and_slide_with_snap(...)` | set `floor_snap_length` → `move_and_slide()` |
|
|
46
|
+
| `connect("sig", obj, "method", [args])` | `obj.sig.connect(method.bind(args))` (Callable) |
|
|
47
|
+
| `disconnect("sig", obj, "method")` | `obj.sig.disconnect(method)` |
|
|
48
|
+
| `emit_signal("sig", a)` | `sig.emit(a)` (string form still exists but prefer the property) |
|
|
49
|
+
| `is_connected("sig", obj, "m")` | `sig.is_connected(m)` |
|
|
50
|
+
| `call_deferred("method", a)` | `method.bind(a).call_deferred()` or `call_deferred("method", a)` |
|
|
51
|
+
| `File.new()` + `open()` | `FileAccess.open(path, FileAccess.READ)` |
|
|
52
|
+
| `Directory.new()` | `DirAccess.open(path)` / `DirAccess.dir_exists_absolute(...)` |
|
|
53
|
+
| `OS.get_ticks_msec()` | `Time.get_ticks_msec()` |
|
|
54
|
+
| `OS.get_datetime()` | `Time.get_datetime_dict_from_system()` |
|
|
55
|
+
| `PoolByteArray` / `PoolStringArray` / `PoolVector2Array` | `PackedByteArray` / `PackedStringArray` / `PackedVector2Array` |
|
|
56
|
+
| `Tween` node + `interpolate_property` | `var t := create_tween(); t.tween_property(node, "position", target, 0.5)` |
|
|
57
|
+
| `rand_range(a, b)` | `randf_range(a, b)` (float) / `randi_range(a, b)` (int) |
|
|
58
|
+
| `deg2rad` / `rad2deg` | `deg_to_rad` / `rad_to_deg` |
|
|
59
|
+
| `stepify(x, s)` | `snapped(x, s)` |
|
|
60
|
+
| `.empty()` | `.is_empty()` |
|
|
61
|
+
| `get_node("Path")` still valid | prefer `%UniqueName` for refactor-safety |
|
|
62
|
+
| `KEY_*` / input constants mostly renamed | check `Key`, `MouseButton` enums |
|
|
63
|
+
|
|
64
|
+
## Silent behavior changes (compile clean, act wrong)
|
|
65
|
+
|
|
66
|
+
- **`Array.slice(begin, end, step, deep)`** — `end` is **exclusive** in Godot 4 (was inclusive in 3).
|
|
67
|
+
`[10,20,30,40].slice(1,3)` → `[20,30]`.
|
|
68
|
+
- **`Camera2D.zoom`** — meaning **inverted**. Larger value = zoom **in**. `zoom = Vector2(2,2)`
|
|
69
|
+
magnifies 2×; in Godot 3 that zoomed out. To zoom out now, use values **below** 1.
|
|
70
|
+
- **Y-sort** is a property (`y_sort_enabled`), not a node — porting a `YSort` parent silently loses
|
|
71
|
+
sorting unless you set the property.
|
|
72
|
+
- **Physics interpolation / gravity** — read gravity via `get_gravity()` (2D/3D) or
|
|
73
|
+
`ProjectSettings`; the old default constants changed.
|
|
74
|
+
- **Signal argument order** on some built-in signals changed; verify against the 4.x docs, don't
|
|
75
|
+
assume the 3.x signature.
|
|
76
|
+
- **`_ready`/`_process` no longer auto-call the base** — you must `super()` when extending a script
|
|
77
|
+
that defines them.
|
|
78
|
+
- **Integer division** with typed ints truncates as expected; mixing float/int in Godot 4 follows
|
|
79
|
+
stricter typed rules — annotate to avoid surprises.
|
|
80
|
+
|
|
81
|
+
## Porting workflow
|
|
82
|
+
|
|
83
|
+
1. Open the Godot 3 project in Godot 4 → run the built-in **Project Converter** (backs up first).
|
|
84
|
+
2. Fix red parse errors top-down (renames above).
|
|
85
|
+
3. Search the codebase for each string-form `connect(`, `yield(`, `.instance()`, `File.new`,
|
|
86
|
+
`Directory.new`, `Pool*Array`, `move_and_slide(` with args — the converter misses some.
|
|
87
|
+
4. Fix the silent-breakers deliberately (slice bounds, Camera2D zoom, y-sort) — tests or a manual
|
|
88
|
+
pass, since nothing errors.
|
|
89
|
+
5. Re-open every scene once; a converter-mangled `.tscn` fails loudly in the editor.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Nodes, scenes, scripts & custom Resources (Godot 4.x)
|
|
2
|
+
|
|
3
|
+
The four building blocks and when each is the right tool. Getting this decomposition right is what
|
|
4
|
+
separates a maintainable Godot project from a monolithic scene that nobody can touch.
|
|
5
|
+
|
|
6
|
+
## The mental model
|
|
7
|
+
|
|
8
|
+
- **Node** — a live object in the running tree. It has a transform (2D/3D), can render, process,
|
|
9
|
+
collide, receive input. Everything on screen is a node. Pick the most specific typed subclass
|
|
10
|
+
(`Sprite2D`, `Area3D`, `CharacterBody2D`, `Timer`, `AudioStreamPlayer`).
|
|
11
|
+
- **Scene** (`.tscn`) — a saved tree of nodes with a designated **root**, instanceable N times. The
|
|
12
|
+
reusable unit of a Godot game. A scene can instance other scenes (composition).
|
|
13
|
+
- **Script** (`.gd` / `.cs`) — code attached to one node, giving it behavior. Attach to the scene
|
|
14
|
+
root; treat children as parts the root drives.
|
|
15
|
+
- **Resource** (`.tres` / `.res`) — a reference-counted **data** object, not in the tree. Textures,
|
|
16
|
+
audio, materials are Resources; so are your **custom** data classes.
|
|
17
|
+
|
|
18
|
+
## Composition over inheritance / deep trees
|
|
19
|
+
|
|
20
|
+
Prefer assembling small scenes over one giant tree or a deep script inheritance chain.
|
|
21
|
+
|
|
22
|
+
- A `Player` scene = `CharacterBody2D` root + `Sprite2D` + `CollisionShape2D` + `Camera2D` +
|
|
23
|
+
instanced `HealthComponent` + `HurtboxComponent` sub-scenes.
|
|
24
|
+
- Behaviors as **components**: a `HealthComponent` (its own scene/script exposing `signal died`) can
|
|
25
|
+
be dropped onto a player, an enemy, or a crate — no shared base class needed.
|
|
26
|
+
- Reach for `extends MyBase` only for genuine "is-a" specialization; reach for composed child nodes
|
|
27
|
+
for "has-a" behavior. The latter is the Godot-idiomatic default.
|
|
28
|
+
|
|
29
|
+
## `class_name` — when to register a global type
|
|
30
|
+
|
|
31
|
+
```gdscript
|
|
32
|
+
class_name HealthComponent extends Node
|
|
33
|
+
signal died
|
|
34
|
+
@export var max_health := 100
|
|
35
|
+
var _current := max_health
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- Register (`class_name`) reusable scripts and **all** custom Resources — it enables `is`/`as`
|
|
39
|
+
checks, `HealthComponent.new()`, and a proper inspector type/slot.
|
|
40
|
+
- Skip it for one-off scene-root scripts that nothing else references by type.
|
|
41
|
+
- Names are global and must be unique across the project.
|
|
42
|
+
|
|
43
|
+
## Custom Resources — typed game data
|
|
44
|
+
|
|
45
|
+
Use a custom `Resource` instead of loose `Dictionary`/JSON whenever you have structured game data:
|
|
46
|
+
stats, items, dialogue lines, wave definitions, ability configs. You get inspector editing, type
|
|
47
|
+
safety, `@export` slots, and save/load for free.
|
|
48
|
+
|
|
49
|
+
```gdscript
|
|
50
|
+
# item.gd
|
|
51
|
+
class_name Item extends Resource
|
|
52
|
+
@export var display_name: String = ""
|
|
53
|
+
@export var icon: Texture2D
|
|
54
|
+
@export var max_stack: int = 99
|
|
55
|
+
@export var value: int = 0
|
|
56
|
+
```
|
|
57
|
+
```gdscript
|
|
58
|
+
# Use it as a typed @export slot on any node:
|
|
59
|
+
@export var starting_items: Array[Item] = []
|
|
60
|
+
|
|
61
|
+
# Create/save/load in code:
|
|
62
|
+
var potion := Item.new()
|
|
63
|
+
potion.display_name = "Potion"
|
|
64
|
+
ResourceSaver.save(potion, "res://data/potion.tres")
|
|
65
|
+
var loaded := load("res://data/potion.tres") as Item
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Gotcha — shared vs unique**: a Resource assigned in the inspector is **shared by reference** across
|
|
69
|
+
all instances by default. If each node must own its copy (e.g. runtime-mutated stats), enable
|
|
70
|
+
**Local to Scene** on the resource, or `duplicate()` it in `_ready()`. Otherwise mutating one
|
|
71
|
+
enemy's `stats.health` mutates every enemy sharing that `.tres`.
|
|
72
|
+
|
|
73
|
+
## `preload` vs `load`
|
|
74
|
+
|
|
75
|
+
| | `preload("res://x")` | `load("res://x")` |
|
|
76
|
+
| --- | --- | --- |
|
|
77
|
+
| Resolved | parse/compile time | runtime, when the line runs |
|
|
78
|
+
| Path | must be a constant literal | can be a variable/computed |
|
|
79
|
+
| Use for | assets you always need; breaks fast if the path is wrong | dynamic/optional assets, avoiding circular preloads |
|
|
80
|
+
| Returns | the Resource/`PackedScene` | same |
|
|
81
|
+
|
|
82
|
+
```gdscript
|
|
83
|
+
const BULLET := preload("res://bullet.tscn") # PackedScene, baked in
|
|
84
|
+
func shoot() -> void:
|
|
85
|
+
var b := BULLET.instantiate() # -> a Node
|
|
86
|
+
add_child(b)
|
|
87
|
+
|
|
88
|
+
# runtime path
|
|
89
|
+
var scene := load("res://enemies/%s.tscn" % enemy_id) as PackedScene
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Instancing & freeing lifecycle
|
|
93
|
+
|
|
94
|
+
- `PackedScene.instantiate()` → a detached node; add it with `add_child(node)` (or
|
|
95
|
+
`add_sibling`) to bring it into the tree and trigger `_ready`.
|
|
96
|
+
- Free with `queue_free()` (deferred to end of frame — safe during signals/physics). Avoid `free()`
|
|
97
|
+
unless you know the node is out of the tree and not mid-callback.
|
|
98
|
+
- After freeing, guard any retained reference with `is_instance_valid(node)` before touching it.
|
|
99
|
+
- `add_child(node, true)` forces a readable unique name; useful when spawning many of one scene.
|
|
100
|
+
|
|
101
|
+
## `.tscn` / `.tres` are strict text — validation rule
|
|
102
|
+
|
|
103
|
+
Both formats are line-oriented with a header (`[gd_scene load_steps=N format=3 ...]`),
|
|
104
|
+
`[ext_resource ...]` / `[sub_resource ...]` blocks, and `[node ...]` / property lines. A wrong
|
|
105
|
+
`load_steps` count, a dangling `ExtResource("x")` id, or a malformed `[node]` path makes Godot
|
|
106
|
+
refuse to open the file. **Do not machine-generate or hand-edit these beyond trivial value tweaks,
|
|
107
|
+
and always open the project in the editor once before relying on a changed scene** — the editor is
|
|
108
|
+
the only reliable validator. Build data-Resources in code + `ResourceSaver.save()` instead of
|
|
109
|
+
writing `.tres` by hand.
|
package/skills/harness/SKILL.md
CHANGED
|
@@ -11,7 +11,7 @@ profiles: [minimal, core, full]
|
|
|
11
11
|
The **harness** is the control plane of a workspace. A workspace need not be code: it can be a company, an ops desk, a legal archive, a personal knowledge vault. Whatever it is, the harness is the durable apparatus that keeps it operable and legible, made of three parts:
|
|
12
12
|
|
|
13
13
|
- **`01-TOOLS/<PROVIDER>/`** — the operational tooling layer. One folder per external provider, co-locating credentials (`.env`) with the scripts that consume them. Each tool ships a working `test_connection` against the real API.
|
|
14
|
-
- **`02-DOCS/`** — the **Karpathy chaos→knowledge engine**: a domain-agnostic LLM wiki (`inbox/` + `raw/` + `raw/worklog/` + `wiki/` + `wiki/index.md` + `wiki/log.md` + `wiki/gaps.md` + `wiki/scores.json` + the `.base` views), fully embedded in this skill. It feeds from **two on-ramps**: (1) the user drops **any raw file in any format** (PDF, image, CSV, JSON, txt, html…) into `inbox/`, and an **Auto-Ingest Sweep** ("the agent goes for a walk") extracts, classifies, cross-links, and compiles it — and goes further, **discovering un-ingested documents anywhere in the workspace** (a stray `/transcripts`, `/facturas`…), bounded by `.rscignore` and de-duplicated by the `wiki/.ingested.json` ledger, fired automatically at SessionStart (when the inbox has material) and by the daily cron. Ingest is
|
|
14
|
+
- **`02-DOCS/`** — the **Karpathy chaos→knowledge engine**: a domain-agnostic LLM wiki (`inbox/` + `raw/` + `raw/worklog/` + `wiki/` + `wiki/index.md` + `wiki/log.md` + `wiki/gaps.md` + `wiki/scores.json` + the `.base` views), fully embedded in this skill. It feeds from **two on-ramps**: (1) the user drops **any raw file in any format** (PDF, image, CSV, JSON, txt, html…) into `inbox/`, and an **Auto-Ingest Sweep** ("the agent goes for a walk") extracts, classifies, cross-links, and compiles it — and goes further, **discovering un-ingested documents anywhere in the workspace** (a stray `/transcripts`, `/facturas`…), bounded by `.rscignore` and de-duplicated by the `wiki/.ingested.json` ledger, fired automatically at SessionStart (when the inbox has material) and by the daily cron. Ingest keeps the repo clean: a loose file it ingests at the workspace root (or anything in `inbox/`) is **moved into `raw/`** (relocated, never deleted — a dropped PDF ends up in `raw/`, not at the root), while files inside a user-maintained folder are copied and consolidation is proposed; removing a redundant folder needs explicit consent; (2) a **Worklog Sweep** captures **what we do** — every meaningful session of work is itself a `raw` source (`raw/worklog/`) compiled into the wiki, fired by a `PreCompact`/`SessionEnd` hook, by an explicit milestone (a commit), or by the daily curation automation (`references/daily-curation-automation.md`). The `wiki/` is a **100%-OKF-v0.1 bundle** (Google's [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf)) AND an **Obsidian-native** vault at the same time — standard markdown links, OKF-standard YAML frontmatter (Properties), readable filenames, and `.base` views give a real graph + live tables — structure, **not vector DB / embeddings / RAG**. The agent writes it; the human reads it in Obsidian. See `references/wiki-protocol.md` for the protocol, `references/ingest-formats.md` for the multiformat Fetch, `references/wiki-worklog-template.md` for the work capture, and `references/obsidian-scaffolding.md` for the vault scaffolding. Topics are inferred from content (`finanzas/`, `legal/`, `crm/`…), never hardcoded. The wiki **self-improves continuously**: every Ingest, Sweep and Query triggers a Maintenance Pass (deterministic lint, score recomputation, gap detection, Related/See-Also sweep), and every N interactions a Micro-Improve runs. Deep Improve runs on explicit request or via the scheduled daily curation. No external skill needed.
|
|
15
15
|
- **The Knowledge map** — the `## Knowledge map` section of the root `CLAUDE.md` that indexes the wiki (including the `harness/` topic) and is read by every other skill before it works in its area.
|
|
16
16
|
|
|
17
17
|
`harness` is the **protagonist concept**. `init` is the bootstrap front door — it gauges the user, drafts the profile, and hands off the first scaffold. THIS skill (`harness`) is the **ongoing control**: it audits, migrates, scaffolds, sweeps the inbox, and keeps the wiki, the tooling and the Knowledge map honest over the life of the workspace. It also generates root `CLAUDE.md` and `AGENTS.md`, and migrates legacy `XX-*` numbered folders into the canonical layout.
|
|
@@ -105,7 +105,7 @@ harness/
|
|
|
105
105
|
│ ├── inbox-readme-template.md ← the inbox/README.md drop-zone contract
|
|
106
106
|
│ ├── wiki-raw-template.md ← format for raw/<topic>/*.md
|
|
107
107
|
│ ├── wiki-worklog-template.md ← format for raw/worklog/*.md (work-driven capture)
|
|
108
|
-
│ ├── wiki-article-template.md ← format for wiki/<topic>/*.md (
|
|
108
|
+
│ ├── wiki-article-template.md ← format for wiki/<topic>/*.md (OKF frontmatter + markdown links)
|
|
109
109
|
│ ├── wiki-index-template.md ← format for wiki/index.md (machine catalog; .base = human nav)
|
|
110
110
|
│ ├── obsidian-scaffolding.md ← .base views, .gitignore, attachments, .obsidian config
|
|
111
111
|
│ ├── daily-curation-automation.md ← portable scheduled compounding pass (the third trigger)
|
|
@@ -356,7 +356,7 @@ If any of these occur, stop and report:
|
|
|
356
356
|
- `references/inbox-readme-template.md` — the `inbox/README.md` drop-zone contract shown to the user.
|
|
357
357
|
- `references/wiki-raw-template.md` — format for `02-DOCS/raw/<topic>/*.md`.
|
|
358
358
|
- `references/wiki-worklog-template.md` — format for `02-DOCS/raw/worklog/*.md` (the work-driven capture; the session as a raw source).
|
|
359
|
-
- `references/wiki-article-template.md` — format for `02-DOCS/wiki/<topic>/*.md` (
|
|
359
|
+
- `references/wiki-article-template.md` — format for `02-DOCS/wiki/<topic>/*.md` (OKF v0.1 frontmatter + relative markdown links + `## Related`).
|
|
360
360
|
- `references/wiki-index-template.md` — format for `02-DOCS/wiki/index.md` (machine catalog; the `.base` views are the human navigation).
|
|
361
361
|
- `references/obsidian-scaffolding.md` — the vault scaffolding: `.base` views, `.gitignore`, `attachments/`, `.obsidian` config (no vector DB / RAG).
|
|
362
362
|
- `references/daily-curation-automation.md` — portable scheduled compounding pass; on Claude Code wired via the `schedule` skill.
|
|
@@ -39,12 +39,14 @@ Run the daily curation pass for this 02-DOCS second brain.
|
|
|
39
39
|
|
|
40
40
|
Use the harness wiki-protocol.md as the contract. First run the Auto-Ingest Sweep:
|
|
41
41
|
process inbox/, then scan the workspace (minus .rscignore) for un-ingested documents,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
applying Clean-as-you-go (move loose root-level + inbox files into raw/ after a
|
|
43
|
+
verified ingest; copy files nested in user-maintained folders and propose
|
|
44
|
+
consolidation), record them in wiki/.ingested.json, and list ambiguous folders as
|
|
45
|
+
proposals (do not grab them). Then compile pending raw/worklog/ material into wiki/
|
|
46
|
+
pages (update existing before creating new), keep frontmatter + relative markdown
|
|
47
|
+
links OKF-consistent, append significant decisions to wiki/harness/decisions.md,
|
|
48
|
+
refresh the .base-backed navigation, recompute scores.json + the score: property,
|
|
49
|
+
and prepend a dated entry (newest first) to wiki/log.md.
|
|
48
50
|
|
|
49
51
|
Be conservative. If the topic map no longer fits, record a recommendation in
|
|
50
52
|
wiki/gaps.md or a page's Open Questions instead of moving large parts of the
|
|
@@ -31,17 +31,24 @@ not bundled with a specific raw source. Link them from the page that depends on
|
|
|
31
31
|
them. Source-bundled originals stay in `raw/<topic>/_originals/`.
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
## `02-DOCS/.obsidian/app.json` (attachment folder)
|
|
34
|
+
## `02-DOCS/.obsidian/app.json` (attachment folder + OKF link mode)
|
|
35
35
|
|
|
36
36
|
```json
|
|
37
37
|
{
|
|
38
38
|
"attachmentFolderPath": "attachments",
|
|
39
|
-
"newLinkFormat": "
|
|
40
|
-
"useMarkdownLinks":
|
|
39
|
+
"newLinkFormat": "relative",
|
|
40
|
+
"useMarkdownLinks": true,
|
|
41
|
+
"alwaysUpdateLinks": true
|
|
41
42
|
}
|
|
42
43
|
```
|
|
43
44
|
|
|
44
|
-
`useMarkdownLinks:
|
|
45
|
+
`useMarkdownLinks: true` makes new internal links **standard markdown links**, not
|
|
46
|
+
wikilinks — this is what keeps `wiki/` a 100%-OKF-conformant bundle (OKF consumers
|
|
47
|
+
follow markdown links; wikilinks `[[...]]` are non-conformant). `newLinkFormat:
|
|
48
|
+
relative` writes paths relative to the current file (`../topic/page.md`), which OKF
|
|
49
|
+
supports and which resolves both in Obsidian and in any OKF consumer.
|
|
50
|
+
`alwaysUpdateLinks: true` makes Obsidian rewrite those relative links automatically
|
|
51
|
+
on rename, so links survive moves the way wikilinks used to. `userIgnoreFilters`
|
|
45
52
|
(Settings → Files & Links → Excluded files) should hide noise from search/graph:
|
|
46
53
|
`raw/_originals/`, `inbox/_processed/`, `audits/`.
|
|
47
54
|
|
|
@@ -59,7 +66,7 @@ filters:
|
|
|
59
66
|
views:
|
|
60
67
|
- type: table
|
|
61
68
|
name: All Articles
|
|
62
|
-
order: [file.name, topic, status, score,
|
|
69
|
+
order: [file.name, topic, status, score, timestamp]
|
|
63
70
|
sort:
|
|
64
71
|
- property: score
|
|
65
72
|
direction: DESC
|
|
@@ -74,9 +81,9 @@ filters:
|
|
|
74
81
|
views:
|
|
75
82
|
- type: table
|
|
76
83
|
name: Worklog
|
|
77
|
-
order: [file.name, topic,
|
|
84
|
+
order: [file.name, topic, timestamp, status]
|
|
78
85
|
sort:
|
|
79
|
-
- property:
|
|
86
|
+
- property: timestamp
|
|
80
87
|
direction: DESC
|
|
81
88
|
```
|
|
82
89
|
|
|
@@ -89,8 +96,8 @@ filters:
|
|
|
89
96
|
views:
|
|
90
97
|
- type: table
|
|
91
98
|
name: Decisions
|
|
92
|
-
order: [file.name, topic, status,
|
|
99
|
+
order: [file.name, topic, status, timestamp]
|
|
93
100
|
sort:
|
|
94
|
-
- property:
|
|
101
|
+
- property: timestamp
|
|
95
102
|
direction: DESC
|
|
96
103
|
```
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
---
|
|
2
|
+
# OKF v0.1 standard surface — `type` is the only REQUIRED field (non-empty).
|
|
3
|
+
type: article
|
|
2
4
|
title: {Title}
|
|
3
|
-
|
|
5
|
+
description: {One-sentence summary, for previews + search.}
|
|
6
|
+
resource: {URL or path to the underlying source/asset — omit the line if none}
|
|
4
7
|
tags: []
|
|
5
|
-
|
|
8
|
+
timestamp: {YYYY-MM-DDTHH:MM:SSZ}
|
|
9
|
+
# rsc custom fields (OKF allows any; conformant consumers preserve unknown keys)
|
|
10
|
+
aliases: [{old-slug}]
|
|
6
11
|
topic: {topic}
|
|
7
12
|
status: draft
|
|
8
13
|
sources: []
|
|
9
|
-
updated: {YYYY-MM-DD}
|
|
10
14
|
score: 0.0
|
|
11
15
|
---
|
|
12
16
|
|
|
13
17
|
# {Title}
|
|
14
18
|
|
|
15
19
|
> Sources: {Author1, YYYY-MM-DD; Author2, YYYY-MM-DD}
|
|
16
|
-
> Raw: [
|
|
20
|
+
> Raw: [{raw-source-1}](../../raw/{topic}/{raw-source-1}.md); [{raw-source-2}](../../raw/{topic}/{raw-source-2}.md)
|
|
17
21
|
|
|
18
22
|
## Overview
|
|
19
23
|
|
|
@@ -25,19 +29,32 @@ score: 0.0
|
|
|
25
29
|
|
|
26
30
|
## Related
|
|
27
31
|
|
|
28
|
-
{OPTIONAL — include only when cross-references exist. Maintained during lint. Use
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
{OPTIONAL — include only when cross-references exist. Maintained during lint. Use
|
|
33
|
+
standard markdown links (OKF-conformant — they ARE the knowledge graph; an OKF
|
|
34
|
+
consumer follows them, and the Obsidian graph + backlinks render them too):
|
|
35
|
+
- Same topic: `- [Other Article](./other-article.md) — why it connects.`
|
|
36
|
+
- Different topic: `- [Other Article](../other-topic/other-article.md) — why it connects.`
|
|
37
|
+
- With display text: `- [how we say it here](../other-topic/other-article.md) — why it connects.`}
|
|
31
38
|
|
|
32
39
|
<!--
|
|
33
|
-
FRONTMATTER CONTRACT
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
|
|
40
|
+
FRONTMATTER CONTRACT — OKF v0.1 conformant. Powers OKF consumers AND Obsidian
|
|
41
|
+
Properties + Bases + graph (same file, no translation).
|
|
42
|
+
OKF standard surface:
|
|
43
|
+
- type REQUIRED, non-empty. article | decision | worklog | brief | spec | profile.
|
|
44
|
+
(OKF type values are not registered centrally; consumers tolerate unknown ones.)
|
|
45
|
+
- title human-readable; the H1 matches it. Consumers may derive from filename if absent.
|
|
46
|
+
- description single-sentence summary for previews/search.
|
|
47
|
+
- resource URI/path to the underlying asset this concept documents (omit if none).
|
|
48
|
+
- tags cross-cutting qualities ONLY — never the main category (that is `topic`).
|
|
49
|
+
- timestamp ISO 8601 datetime of the last meaningful edit (e.g. 2026-06-28T14:30:00Z).
|
|
50
|
+
rsc custom fields (allowed by OKF; never required for conformance):
|
|
51
|
+
- aliases keep the old kebab slug here so pre-migration links still resolve.
|
|
38
52
|
- topic the wiki/<topic>/ folder, one level. Inferred from content, never hardcoded.
|
|
39
53
|
- status draft | stable | stale (lifecycle; filterable in a Base).
|
|
40
|
-
- sources
|
|
41
|
-
- updated YYYY-MM-DD of the last meaningful edit.
|
|
54
|
+
- sources markdown links to raw/ pages this was distilled from (cite your evidence).
|
|
42
55
|
- score mirror of scores.json, written by the Maintenance Pass (single writer → no drift).
|
|
56
|
+
|
|
57
|
+
LINKS: standard markdown links only — NEVER wikilinks ([[...]]). Relative paths
|
|
58
|
+
(./same-topic.md, ../other-topic/page.md, ../../raw/<topic>/<file>.md). This is
|
|
59
|
+
what keeps wiki/ a portable, 100%-OKF-conformant bundle.
|
|
43
60
|
-->
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Knowledge Base Index
|
|
2
2
|
|
|
3
|
+
> **OKF v0.1 reserved file** — `index.md` carries **no frontmatter** (it is a
|
|
4
|
+
> directory listing for progressive disclosure, per the OKF spec). Links are
|
|
5
|
+
> standard markdown, relative to this file (`topic/article.md`), NEVER wikilinks.
|
|
6
|
+
>
|
|
3
7
|
> **Human navigation lives in the `.base` views** (`Articles.base`, `Worklog.base`,
|
|
4
8
|
> `Decisions.base`) — live tables over frontmatter, sorted by score/status/date.
|
|
5
9
|
> This index is the **machine-readable catalog + fallback** the agent maintains;
|
|
@@ -11,8 +15,8 @@
|
|
|
11
15
|
|
|
12
16
|
| Article | Summary | Updated | Score |
|
|
13
17
|
|---------|---------|---------|-------|
|
|
14
|
-
| [
|
|
15
|
-
| [
|
|
18
|
+
| [{Article Title}]({topic-name}/{article-file}.md) | {One-line summary} | {YYYY-MM-DD} | {N.N} |
|
|
19
|
+
| [{Archived Article}]({topic-name}/{archived-file}.html) | [Archived] {One-line summary} | {YYYY-MM-DD} | {N.N} |
|
|
16
20
|
|
|
17
21
|
## {another-topic}
|
|
18
22
|
|
|
@@ -20,7 +24,7 @@
|
|
|
20
24
|
|
|
21
25
|
| Article | Summary | Updated | Score |
|
|
22
26
|
|---------|---------|---------|-------|
|
|
23
|
-
| [
|
|
27
|
+
| [{Article Title}]({another-topic}/{article-file}.md) | {One-line summary} | {YYYY-MM-DD} | {N.N} |
|
|
24
28
|
|
|
25
29
|
> **Score**: composite quality score (inbound links, source count, cited count,
|
|
26
30
|
> freshness; minus conflicts and orphan penalty). Regenerated on every
|