ワンクリックで
dev-physics-review
Code quality, correctness, and documentation review for physics lessons — run before dev-final-pass
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Code quality, correctness, and documentation review for physics lessons — run before dev-final-pass
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Add PBR texture loading with separate roughness/metallic support to an SDL GPU project using forge_scene.h
Add Cook-Torrance PBR shading with GGX, Schlick-GGX, and Schlick Fresnel to an SDL GPU project alongside forge_scene.h
Add instanced grass rendering with segmented blades, wind animation, LOD density rings, and terrain LOD with geomorphing to an SDL GPU project
Add procedural noise texture generation to the asset pipeline — C tool, Python plugin, web UI with live preview
Add an asset pipeline lesson — hybrid Python + C track for asset processing, procedural geometry, and web frontend
Add an audio lesson — sound playback, mixing, spatial audio, DSP effects, with SDL GPU scenes and forge UI
| name | dev-physics-review |
| description | Code quality, correctness, and documentation review for physics lessons — run before dev-final-pass |
| argument-hint | [lesson-number or lesson-name] |
| disable-model-invocation | false |
Run a physics-specific quality review on a physics lesson before running
/dev-final-pass. This skill catches the recurring code quality, correctness,
and documentation issues specific to forge_physics.h and its callers. It is
not a replacement for /dev-final-pass — it covers the physics-domain concerns
that the general final pass does not.
The user provides:
01 or point-particles)If missing, infer from the current branch name or most recent physics lesson directory.
Work through the three phases below in order. Each phase launches parallel agents. After each phase, validate findings, apply fixes, then have the agents revalidate. Repeat until no more issues are found.
Use a Task agent (model: haiku) for builds, test runs, and linting — never run those directly from the main agent.
Be literal and exhaustive. This is C — no RAII, no garbage collector. Every resource you acquire must be released on every exit path, every struct field must be documented, every error must be handled. Do not rationalize away findings with "it's probably fine." If the check says every function, check every function.
Spawn one agent per concern to review every function added or modified in
common/physics/forge_physics.h, the lesson's main.c, and the relevant test
files (tests/physics/test_physics.c). Each agent works independently and
reports findings.
SDL_malloc/SDL_calloc/SDL_realloc has a matching SDL_free on
every exit path — bare malloc/free must not be used; the codebase uses
SDL's allocation functions exclusivelySDL_free
when the struct is destroyedforge_shapes_free() called for every generated shape after GPU uploadSDL_AppQuitAfter collecting findings from all five agents:
Spawn one agent per check to verify the following across all changed files. The scope for each check is specified in its description.
Scope: all test files in tests/physics/
For setup and success-path code, wrap forge_physics_* calls that return
false on failure with ASSERT_TRUE(...) so tests fail immediately on
unexpected errors.
For negative-path tests that intentionally trigger failures, assert the expected
failure explicitly with ASSERT_FALSE(...) (or equivalent).
What to look for:
forge_physics_integrate(&p, dt) without checking the returnScope: all test files in tests/physics/
Numeric literals representing reusable or semantically meaningful tuning
parameters (masses, forces, timesteps, tolerances, domain constants) should be
defined as #define or enum at the top of the relevant test section. Other
test sections in the same file already follow this convention — new code must
match. One-off literals in a single tightly scoped assertion are acceptable
when they remain clear and do not obscure intent.
Acceptable bare numbers:
0, 1, -1 as trivial loop/comparison values2.0f in 2 * pi)Unacceptable bare numbers:
2.0f, 0.5f)9.81f outside of a named constant)0.016f, 1.0f / 60.0f)0.8f, 0.99f)10.0f, 5.0f)ASSERT_NEAR (1e-4f, 1e-6f)10000)Scope: common/physics/forge_physics.h (all forge_physics_* functions)
Ensure that any arithmetic that could produce inf, NaN, or wildly
incorrect results is handled:
1.0f / mass without checking mass > 0,
or computing inv_mass from an invalid mass value; vec3_normalize()
on a zero-length vector; denominator in impulse calculations
(e.g. sum_inv_mass) must be checked before dividingsqrtf(negative) — squared distance checks should guard against floating-
point rounding producing tiny negative values before taking square rootfloat parameters should reject or clamp non-finite
values at entryvec3_length() > epsilon before dividing[0, 1], damping to [0, 1], penetration
depth to >= 0Scope: common/physics/forge_physics.h (integration and force functions)
Verify that the integration follows the documented algorithm exactly:
v += a * dt then
x += v * dt (using the new velocity), not x += v * dt then
v += a * dt (which is explicit Euler)v *= pow(damping, dt) or v *= damping) not additivea = force * inv_mass, not
a = force / mass (which would divide by zero for static objects)if (inv_mass == 0) return at the top of
integration and force functionsScope: common/physics/forge_physics.h, the lesson's main.c, all
changed test files
Remove any unused variables. Check for:
(void)param; or remove)#define constants that are never referencedtypedef types that are never instantiatedScope: common/physics/forge_physics.h, the lesson's main.c, the
lesson's README.md
Update or remove misleading or incorrect API comments:
Scope: common/physics/forge_physics.h, the lesson's main.c
Ensure the simulation is deterministic with fixed timestep and identical inputs:
rand(), time(), or other non-deterministic functions in the
physics step (randomness for initial conditions is fine, but must use a
seeded RNG that can be reset)PHYSICS_DT is a constant, not derived from frame timeScope: all test files in tests/physics/
Ensure any test setup/helper code that can fail returns a boolean value. If the
helper allocates resources, initializes particles, or calls forge_physics_*
functions, it should return bool and the caller should ASSERT_TRUE on it.
Scope: the lesson's main.c and shaders
Every physics lesson must include the rendering baseline and controls defined
in /dev-physics-lesson. Verify each item is present — the review FAILS if
any are missing:
Rendering baseline (all required):
quat_from_euler, mat4_view_from_quat)forge_shapes.h (no inline
geometry generation functions, no model loading)ForgeShape data must be converted to
ForgeSceneVertex format and uploaded via forge_scene_upload_buffer, not
raw SDL_CreateGPUBuffer. Direct SoA upload produces broken geometry
because forge_scene.h shaders expect interleaved AoS vertex data.ForgeUiWindowState must be initialized
with forge_ui_window_state_default(x, y, w, h) before useSimulation controls (all required):
Deliverables (all required):
assets/screenshot.png exists or capture support is wiredassets/animation.gif exists or GIF capture is wired
(physics is dynamic — a static screenshot alone is insufficient)After completing checks 3, 4, and 7, write dedicated tests for every finding and for the general cases covered:
INFINITY,
NAN, zero-length vectors, and zero dt to functions and verify they return
false or produce clamped/safe output. Run long simulations (10000+ steps)
and verify no position or velocity becomes NaN or infinity.All new tests must follow the guidelines from checks 1 and 2:
forge_physics_* calls with ASSERT_TRUE where they return bool#define constants at the top of the test sectionAfter collecting findings from all eight checks:
Spawn one agent per check to verify documentation quality.
Scope: common/physics/forge_physics.h
Verify that every struct field has an inline comment explaining:
inv_mass is
precomputed from mass)Bad: float mass; /* mass */
Good: float mass; /* kg — zero means infinite mass (immovable object) */
Verify that every function has a doc comment with:
Scope: the lesson's README.md
Verify that any KaTeX math notation follows the same conventions as other forge-gpu lessons:
Inline math uses $...$ (single dollar signs)
Display math uses three-line format:
$$
formula here
$$
Variable names are consistent with the code (\text{velocity} matches
velocity, \Delta t matches dt)
Formulas are correct and match the implementation in forge_physics.h
and main.c
Symplectic Euler equations show velocity updated before position
Scope: any diagram scripts modified or added for this lesson
Verify diagrams adhere to the /dev-create-diagram skill guidelines:
STYLE dict — no hardcoded colorspath_effects readability strokepad >= 12DIAGRAMS dict in __main__.py__init__.py
(e.g. scripts/forge_diagrams/physics/__init__.py) — the reorg'd
structure requires both __main__.py registration and track-level exportruff check and ruff format --checkScope: the lesson's README.md, main.c, and common/physics/forge_physics.h
Verify that every code snippet, function signature, struct definition, and API
example shown in the README exactly matches the actual code in
forge_physics.h and main.c. Check for:
Scope: README.md (root), lessons/physics/README.md,
common/physics/README.md, CLAUDE.md, PLAN.md
Verify all index files are up to date with the changes from this lesson:
README.md: Physics lessons section has a row for this lesson
(create the section if this is the first physics lesson)lessons/physics/README.md: lessons table includes this lessoncommon/physics/README.md: all new types and functions added to the
library are documented in the API reference; the lesson appears in
"Where It's Used"CLAUDE.md: if the lesson changes project structure, conventions, or
adds new modules, CLAUDE.md reflects those changesPLAN.md: the physics lesson entry is checked offAfter collecting findings from all five doc checks:
After completing all phases, report a summary table:
Physics Review Results — Lesson NN: Name
==========================================
Phase 1 — Code Correctness
Memory safety ✅ PASS (N functions checked)
Parameter validation ✅ PASS (N functions checked)
Bug detection ✅ PASS
Undefined behavior ✅ PASS
Resource cleanup ✅ PASS
Phase 2 — Verification Checks
1. Test assertions ✅ PASS (N calls wrapped)
2. Magic numbers ⚠️ FIXED (N constants extracted)
3. Numerical safety ✅ PASS (N guards added, N tests written)
4. Integration correct. ✅ PASS (N paths checked, N tests written)
5. Unused variables ✅ PASS
6. Comment accuracy ✅ PASS
7. Determinism ✅ PASS (N tests written)
8. Setup returns ✅ PASS
9. Lesson contract ✅ PASS (rendering baseline, controls, deliverables)
Phase 3 — Documentation
1. Struct/function docs ✅ PASS (N fields, N functions documented)
2. KaTeX consistency ✅ PASS
3. Diagram compliance ⏭️ SKIP (no diagrams modified)
4. README accuracy ✅ PASS
5. README currency ✅ PASS
For each WARN, FIXED, or FAIL, list the specific file, line, and issue with
the fix applied (or suggested if not yet applied). Ask the user if they want
to proceed to /dev-final-pass.