Skip to content

feat(depth): what the sheet is not, and whether the ceiling read a form - #455

Merged
firejune merged 1 commit into
mainfrom
feat/what-the-sheet-is-not
Sep 7, 2026
Merged

feat(depth): what the sheet is not, and whether the ceiling read a form#455
firejune merged 1 commit into
mainfrom
feat/what-the-sheet-is-not

Conversation

@firejune

@firejune firejune commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Closes #448, closes #449.

bun run typecheck clean, bun run lint clean, bun run selftest 568 PASS / 0 FAIL / 0 SKIP / 0 HOLE, exit 0 (564 on main). The +4 is DP05, DP06, DP07 and TC07.

🔒 No summary figure was edited — confirmed rather than assumed: the contour suite's own clause moved 30 → 34 on its own. This is the second PR today where #452's tally paid for itself.

#449 — the same defect, two encodings, and the same number from both

sampleMeshDepth refuses a depth sheet that does not cover the mesh, but the check sat behind if (!opaqueEverywhere), so a sheet with no transparent texel anywhere skipped it entirely — and a sheet produced by monocular depth estimation is exactly that.

Measured here on a synthetic fixture: a 9×9 lattice over a 97×65 window whose art is the rectangle [20,78)×[12,54), one ramp field stored two ways.

the sheet's alpha what rigc does
cut to the art REFUSEDdoes not cover 56 of the mesh's 81 vertices
opaque everywhere COMPILED56 of 81 vertices sample a texel the part image does not draw, range [0, 50], ceiling 62.40°

The refusal's count and the report's count are the same 56, reached from opposite inputs. The two sheets are proven one depth field by digest — af4ec072504122b7 both, since depthDigest is over levels only — so only the alpha differs. And 56 is confirmed three independent ways: the report, the lattice's own arithmetic (81 − 5×5), and the rectangle predicate applied to the 81 vertex positions read back through spine-core.

The measurement is a report, not a refusal. A full-frame sheet is a legitimate statement and rigc has no authority to guess an input away (#391); how many vertices sample undrawn art is a measurement.

The header's reasoning was measurably false and is gone

It justified the gate with "…what the background level means is then the author's statement, and range in the report is where it shows up." On the tested build range reads [0, 223.97] of 224 — full and healthy — over a mesh 54 % of which samples background. Replaced by what actually shows one, which is the new count.

🔸 The flagship example says something it never has

gallery/look's own head mesh takes 80 of 189 vertices (42 %) from texels head.png does not draw — the border of a lattice over a cut-out head. Not a defect: its step share of 0.112 says the ceiling read a form. It is simply the first time the tool has said it, and the README now says what it is.

#448stepShare, and the separation reproduced on synthetic sheets

stepShare is depthStep ÷ (range[1] − range[0]): one divide of two numbers turnCeiling already held, reported beside the step. A form's share halves under refinement while its ceiling converges; a discontinuity pins its share and halves its ceiling instead, because there is no slope to converge to.

TC07 builds both on one lattice ladder — a raised cosine, and half that cosine plus a jump of the other half at a texel column no lattice vertex lands on:

grid-9 grid-17 grid-33
form, ceiling 41.99° 39.59° 38.84°
form, stepShare 0.3579 0.1947 0.1000
cliff, ceiling 37.07° 18.59° 9.24°
cliff, stepShare 0.4602 0.4892 0.4974

Form share ×1.838 / ×1.947 per doubling with tangent ×1.088 / ×1.027; cliff share ×0.941 / ×0.984 with tangent ×2.247 / ×2.066. The cliff was planted at 0.500 by construction and the finest rung reads 0.4974. Lowest cliff reading is above the highest form reading, 5.0× apart at the finest rung.

⚠️ These are not #448's digits and must not be read as reproducing them. That study used a different window, amplitude and cliff placement. What reproduces is the behaviour — and the tangent ratios sit beside the study's measured 2.02 / 1.95 / 2.02.

The one figure whose subject is reachable from this repository does reproduce exactly: gallery/look reads 0.112 and 0.468, from an independent implementation of the divide.

🔒 No threshold anywhere, and nothing in src/ reads the number. Whether any cutoff is defensible is unsettled; the figure is reported so an author can see which kind of thing the ceiling read.

The contour rim, and the option that was rejected

A contour's vertices are all traced outline pushed out by the margin, so the count is its whole rim on every rig — margin 1, 2 and 4 all read 15 of 15, opaque sheet or correctly dilated. A line that constant teaches a reader to ignore it.

Discounting by the margin was refused, and that refusal stands. On a dilated sheet the rim's depth is the art's and the line is noise; on a full-frame estimate the rim's depth is the background and the line is the whole failure — and rigc cannot tell those apart from the part's alpha. Borrowing a number authored for the trace to mean "close enough" for the sheet is the reach the soft header already calls out.

What shipped instead is a structural attribution, and only on a contour, where the generator already knows: buildContourMesh returns its vertices as offsetPolygon(simplified, margin), so nothing is re-traced, nothing is read off position, and no threshold is involved.

15 of 15 vertices sample a texel the part image does not draw — a contour's vertices are
all traced outline, pushed out by the margin, so this is the topology and not the sheet

A grid's border is where the author's us/vs put it rather than where a margin did, so calling it a rim there would be a lie; the grid's line is unchanged.

⚠️ A count was measured, and rejected because it separates nothing

Before writing the attribution, the obvious version — how many of the undrawn are on the hull — was measured against the emitted skeleton's own hull plus the part PNGs:

mesh vertices hull undrawn on the hull interior
contour probe (margin 2) 15 15 15 15 0
look/head (grid) 189 56 80 56 24
look/hair_lock_l 39 28 32 28 4
look/hair_lock_r 39 28 32 28 4

On every depth mesh reachable here the entire hull is undrawn, so a hull count would restate a number already in the artifact. What varies is the interior count — filed as a follow-up rather than shipped, because it is a second decision.

Mutants — six, each planted in the real file and restored by checksum

mutant what fired
the count never fires (partAlpha[at] === 256) DP05 + DP06 + DP07this mutant is the defect, and it restores exactly the silence #449 describes
the count fires on everything (>= 0) DP05 + DP06; DP07 correctly survives, which is why DP06 exists
divide by zHi rather than the span TC07
the step, unnormalised TC07
cli.ts prints the step where the share belongs TC07, subprocess clause only
the attribution swapped to the wrong kind DP07 and GT01/GT02/GT03/GT05

The two that teach something are M3 and M4. Every ratio clause survived both. M3 was caught only by "planted at 0.500" — and only because the fixture's sheets sit on a base of 64 levels, since with a sheet reaching 0 the span and the maximum are the same number and the mutant is invisible; that reason is written into the fixture. M4 was caught only by the bounds clause, an arithmetic invariant rather than a measurement: a share of a range cannot exceed 1.

🔁 That is this repository's recurring lesson from a new angle — a check that only compares a thing to itself cannot see a uniform error, and what saves it is an absolute anchor.

⭐ And the last mutant is the regeneration proving itself: mis-attributing the clause takes the two gallery/look blocks out of GT02 and drops GT01/GT03/GT05's populations 18→16, 92→82, 14→12. A gate whose population shrank is a gate switched off, seen firing.

The gallery quotes, regenerated from a real run

gallery/look/README.md was the only README quoting a depth block — established by grepping every gallery/*/README.md for five markers, not assumed. nod and portrait carry depth in their motion specs and quote no block; look's third MESH quote has soft and no depth.

Regenerated by running the README's own stated command and splicing its stdout under assertion, never typed. The --images form AUTHORING states was verified to print a byte-identical block, and the doc block was verified equal to the run.

GT01GT05 populations before → after: nothing shrank, and one figure grew — GT02's verified line count 92 → 94, exactly the two lines the two blocks gained.

Also found and fixed on the way

src/types.ts had a displaced doc comment. The block beginning "What a depth map put on this mesh's vertices…" sat above soft?: rather than depth?:, two doc comments stacked with the first orphaned. Moved back, with the drift noted in it. CUR07's shape one file over: nothing derives a doc comment's neighbour.

A fixture hazard, recorded rather than worked around. depthLevels truncates into a Uint8Array, so a fixture stating AMP/2 = 95.5 would plant a 95-level cliff while believing it planted 95.5. The fixture uses an even amplitude and rounds every level explicitly, with the reason in the comment.

Deliberate non-choices

  • No division guard on stepShare. It is in (0,1] by construction — a fold needs two vertices at different depths, so the mesh's span is at least the step. A guard would be an unreachable branch, and an unreachable branch is not a control (Promote the editor round-trip harness into tools/ as a documented, editor-requiring tool #374). The comment says so at the divide.
  • undrawn is always present and 0 is a real answer. Every mesh naming a depth map also names an image, so the measurement is always taken; unlike p1, a null state would be wrong here.
  • Alpha 0, not a threshold. Any other cut-off would be rigc deciding how faint a texel has to be before it stops being art.
  • Fixtures are inline probes, not fixtures/public.ts. The depth suite's synthetic sheets already live in selftest.ts as that tier, and these are the same kind of thing on the same route.

Not checked, stated plainly

#449's 2,272 of 4,225 and every estimated-sheet column in #448 — the material is deliberately not in this repository and was not sought. Nothing measured here contradicts any figure in either card. bench and check were not run: both changes are report-only, and neither field reaches skeleton.json or skeleton.atlas (0 hits on a gallery/look build).

sampleMeshDepth refused a sheet that does not cover the mesh, but the check was
gated behind a sheet having any transparent texel at all, so a full-frame opaque
render skipped it entirely. A sheet produced by monocular depth estimation is
exactly that. The same defect was a named refusal in one encoding and a green
build in the other.

The coverage instinct now reaches the part's alpha and reports rather than
refuses, in the same loop and the same four taps as the refusal. A full-frame
sheet is a legitimate statement and rigc has no authority to guess an input
away; how many of the mesh's vertices sample a texel the part image does not
draw is a measurement, not a guess.

The module header justified the old gate with a sentence that is measurably
false: range does not show a background-sampling mesh. On the tested build it
reads full and healthy over a mesh half of which samples background. It is
replaced by what actually shows one.

stepShare is depthStep over the range the mesh sampled, one divide of two
numbers turnCeiling already held. A form's share halves under refinement while
its ceiling converges; a discontinuity pins its share and halves its ceiling
instead, because there is no slope to converge to. Both existing diagnostics
read healthy on the second case and this one separates them. No threshold: the
number is reported so an author can see which kind of thing the ceiling read.

A contour's vertices are all traced outline pushed out by the margin, so the
count is its whole rim on every rig. Discounting it by the margin would borrow a
number authored for the trace to mean close enough for the sheet. The report
names the topology instead, and only on a contour, where the generator already
knows the vertices are the outline it traced.

Closes #448, closes #449.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@firejune
firejune enabled auto-merge (squash) September 7, 2026 05:26
@firejune
firejune merged commit dfcd808 into main Sep 7, 2026
1 check passed
@firejune
firejune deleted the feat/what-the-sheet-is-not branch September 7, 2026 05:29
@github-actions github-actions Bot mentioned this pull request Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant