agentsclimarketplace

Srib model

Skill sayonsom/srib-godot-skills-demo/.claude/skills/srib-model

Standalone proof that six Claude Code skills develop a Godot 4.6 feature end-to-end: from an Excel backlog to a runnable SmartThings home view (shaders, animation, UI, integration). Includes one-step Linux/Windows setup.

Install
npx -y skills add sayonsom/srib-godot-skills-demo --skill srib-model

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Implement model-layer features in the SRIB Godot 4.6 Android app — mathematical models, animation curves, tweens, easing functions, physics behaviors, interpolation, state machines, simulation logic, data processing, and GDScript computation that is independent of rendering. Use when a feature is about how something moves, evolves, computes, or processes data over time. Triggered by: "srib-model", "implement the animation logic", "add the state machine", "fix the easing", "compute the device state", "physics behavior", or any SRIB ticket classified as "model" by srib-identify. Do NOT use for shader/visual work (srib-view) or connecting data to scene nodes (srib-integration). Always read the ticket from issues/SRIB-NNN.md before starting.

SKILL.md

6.6 KB, as published. Nobody here has run it

srib-model

Project: SRIB — Godot 4.6 Android application with a 3D SmartThings home view. Role: Math and behaviour layer. Everything about how values change, objects move, and data gets processed — independent of how anything is drawn.


Invocation

srib-model SRIB-NNN

Read issues/SRIB-NNN.md for the full spec. If no ticket is given, ask the user to describe the behaviour and confirm the scope before implementing.


Scope boundary

The model layer produces values. The view layer consumes them. Never import a ShaderMaterial or call set_shader_parameter from a model script — that belongs in srib-integration. Model scripts emit signals or expose properties that integration scripts read.

Model script (RoomModel.gd)
  → emits: visual_params_changed(params: Dictionary)
  ← never references: MeshInstance3D, ShaderMaterial, CanvasItem

Workflow

Step 1 — Read the ticket and locate relevant files

cat issues/SRIB-NNN.md
find . -name "*.gd" -path "*/scripts/*" | head -30
grep -r "AnimationPlayer\|Tween\|StateMachine" --include="*.gd" -l

Identify: which GDScript file owns this behaviour, and what signals it emits or receives.

Step 2 — Choose the right animation / computation approach

Use this decision table before writing any code:

SituationRecommended approach
One-shot transition (e.g., door open animation)Tween — create, tween_property, play
Looping animation (e.g., breathing light)AnimationPlayer with looped animation, or Tween with set_loops(0)
Interruptible transition (e.g., user taps mid-animation)Tween — kill previous, create new
Complex multi-state object (e.g., AC unit: off/cooling/heating/fan-only)StateMachine pattern (see below)
Physics-influenced motionGodot physics body + _physics_process
Frame-rate-independent value smoothinglerp(current, target, weight * delta) or spring function
Single computed property with no time dimensionPure function, called on data change

Step 3 — Implement

Tween pattern (preferred for UI/device state transitions):

var _tween: Tween

func transition_to_on() -> void:
    if _tween:
        _tween.kill()
    _tween = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC)
    _tween.tween_property(self, "emissive_value", 1.0, 0.4)
    _tween.finished.connect(_on_transition_done)

Easing cookbook:

FeelEase typeTrans type
Snappy, physicalEASE_OUTTRANS_SPRING
Smooth UI slideEASE_IN_OUTTRANS_CUBIC
Elastic bounceEASE_OUTTRANS_ELASTIC
Sudden stopEASE_INTRANS_EXPO
Linear progressTRANS_LINEAR

State machine pattern (for multi-state devices):

enum State { OFF, IDLE, ACTIVE, ALERT }

var _state: State = State.OFF

func set_state(new_state: State) -> void:
    if _state == new_state:
        return
    _exit_state(_state)
    _state = new_state
    _enter_state(_state)
    state_changed.emit(_state)

func _enter_state(s: State) -> void:
    match s:
        State.ACTIVE:
            _start_pulse_animation()
        State.ALERT:
            _start_alert_animation()
        _:
            _stop_all_animations()

func _exit_state(s: State) -> void:
    pass  # cleanup if needed

Spring / damped lerp (for smooth camera or position following):

# Call in _process(delta). velocity is a member var.
func spring_lerp(current: float, target: float, velocity: float, stiffness: float, damping: float, delta: float) -> Array:
    var spring_force = (target - current) * stiffness
    var damping_force = -velocity * damping
    velocity += (spring_force + damping_force) * delta
    current += velocity * delta
    return [current, velocity]

Bezier curve evaluation (for custom easing on shader params):

static func cubic_bezier(p0: float, p1: float, p2: float, p3: float, t: float) -> float:
    var u := 1.0 - t
    return u*u*u*p0 + 3.0*u*u*t*p1 + 3.0*u*t*t*p2 + t*t*t*p3

Step 4 — Signal contract

Every model script that feeds the view layer must document its signal contract in a comment block at the top:

## Emitted when visual parameters change.
## params keys: "emissive_strength" (float 0..1), "base_color" (Color), "pulse_phase" (float 0..1)
signal visual_params_changed(params: Dictionary)

This contract is what srib-integration uses to wire the view. Be explicit and stable.

Step 5 — Test

  1. Write a small test scene or use an existing debug scene
  2. Print signal emissions to Output — verify values are in expected ranges
  3. Test edge cases: rapid state toggling, delta = 0, extreme values
  4. Confirm no _process or _physics_process callbacks run when the node is not needed (use set_process(false) when idle)

GDScript conventions for model code

  • Model nodes extend Node (not Node3D or Control) — they hold no visual representation
  • Use @export for tunable constants (ease values, speeds) so they're editable in the Inspector without code changes
  • Prefer @onready over get_node() in _ready()
  • Use type hints everywhere: var velocity: float = 0.0, func set_state(s: State) -> void:
  • delta must be passed to all time-dependent functions — never use Time.get_ticks_msec() for animation logic

Acceptance checklist

  • Logic matches ticket description — values transition correctly
  • Signals emit with documented keys and types
  • No direct references to visual nodes (MeshInstance3D, ShaderMaterial, etc.)
  • Edge cases handled: rapid transitions, zero delta, extreme input values
  • Tested in editor (Play Scene, verify Output panel shows expected signal emissions)
  • @export vars used for tunable constants (ease, speed, threshold)
  • Type hints on all method signatures and member vars
  • No regressions in existing model scripts

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.