docs(skill): the surface table, rig anchors, and asserting the consequence

The skill is this project's own instructions, and three commits made it wrong:
it described a runtime that re-guessed what every surface was, a lab that only
tuned weapon holds, and a suite that could not see any of the last five defects.
It also still listed a seventh character that is not in skins.json.

Records what is new — the surface table and how it is decided, the layered
tuning files and why a fixed rotation on the weapon mount is the wrong answer,
the rig lab — and what the work taught:

  * assert the CONSEQUENCE. Asking a model which clip it is playing reads a
    variable it set on itself, and says "Idle" just as happily when nothing is
    ticking. Asking whether an anchor saved says nothing about whether the gun
    moved.
  * four of the last five real defects came from looking at a PNG. Every one of
    them passed every assertion.
  * the line-work rule now exists twice, at build time and as the runtime
    fallback, and they must be changed together or a model with a surface table
    starts rendering differently from one without.

Also records momo's broken idle and the stray Icosphere under known-unsolved,
with what is worth suspecting first in each case, since neither is fixed.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Nicholas Butzke
2026-07-27 15:00:42 -04:00
co-authored by Claude Opus 5
parent 99a2ee131d
commit 1e6f3001ac
4 changed files with 199 additions and 21 deletions
@@ -41,7 +41,36 @@ Two related traps:
| `travel_dir_check.gd` | stride direction vs. travel direction | < 10° except a capped sidestep |
| `limb_deform_check.gd` | joint collapse | knee ~0.99 |
| `verify_character.py` | meshes, bones, weights of a SOURCE model | several meshes, cloth bones present |
| `surface_class_check.gd` | every surface resolves from the sidecar, not the fallback | 0 fallbacks on all six skins |
| `character_picker_check.gd` | the escape-menu roster: skeleton, clips, surfaces, and that the pose MOVES | 0 failures |
| `rig_anchor_check.gd` | a grip anchor physically moves the weapon, and clears | 0 failures |
| `anim_capture.gd` / `orbit_capture.gd` | renders, for looking | — |
| `roster_capture.gd` | one photo of every character, from the picker | — |
| `ui_capture.gd` | one photo of every menu screen | — |
## Assert the consequence, not the plumbing
Three of these exist because the obvious check passes on a broken system.
- `character_picker_check` asserts the skeleton's pose CHANGES over a dozen
frames. Asking the model which clip it is playing does not work: that is a
variable the class sets on itself, and it reads `"Idle"` just as happily when
the animation tree is not ticking at all.
- `rig_anchor_check` asserts the weapon MOVES by the offset asked for. An anchor
system is easy to build so that the sliders move, the file saves and the JSON
round-trips while the gun does not budge — the value read into a variable
nobody consumed. It measures in the attachment's frame, not the world's:
the attachment tracks a bone on an animating skeleton, so a world-space delta
is mostly the idle animation.
- `surface_class_check` FAILS on a surface that falls through to the heuristic
instead of resolving from the table. A model whose names stopped matching still
renders — the fallback catches it — and quietly loses its per-class art
direction. Nothing else would report that.
And four of the last five real defects came from LOOKING, not from asserting:
a preview showing the back of the character's head, a turntable that carried on
from the previous character, an unstyled list, and momo's idle pose. Every one
passed every assertion. Run `roster_capture` and `ui_capture` and open the PNGs.
Run them: