docs(stage): the stage learns centimeters — ADR 0036 and its story #161
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "docs/stage-in-centimeters"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Drafts the physical-stage-scale model from today's design discussion as ADR 0036 (Accepted) plus a new story, with pointers threaded through the existing docs.
The model (ADR 0036)
Four authored parameters, all cm-denominated, one pure projection:
cowboy shotdefault-tag workaround) and calibrates the sprite's nominal cm span for the renderer. Existing characters migrate to cowboy shot. Stored contract likeStagePosition.Plus the crop-edge invariant, scoped to cropped framings (
c < 1):elevation + (1 − coverage) × height ≤ viewBottom, or the cut line shows. Full body has no cut line and floats freely. Enforcement splits by cause — elevation on a cropped framing refuses loudly ("a cowboy-framed sprite can't float"); standing-height jitter at the frame bottom is silently absorbed by the renderer clamp (which is today's bottom-anchoring). The renderer stays total.The story
stories/stage-in-centimeters.mdcarries the requirements and acceptance criteria, including the whelp test: a 94 cm full-body floater at elevation 100 beside a 172 cm cowboy-framed adult, exactly scaled. Priority rides a new[Next]tier (accepted and pulled forward), defined in the REQUIREMENTS conventions. Implementation ordering lives in the ADR's consequences, not the story.Also touched
Cross-reference stubs in the character-sprites, scene-editor, and player-preview stories;
[Next]requirement lines in REQUIREMENTS §2/§5/§6; ADR index entry; a "next up" bullet in the project plan.Honest caveats documented: nominal framing tolerance is ±5–10 % (ratios between characters stay exact regardless), backgrounds remain uncalibrated backdrops, and the rollout must remove the global
cowboy shottag or generations get double-tagged.Review round 1 (owner): accepted, pulled forward to
[Next], slices moved out of the story. Round 2 (Jibril): invariant scoped to cropped framings; default view bottom 75 → 78.🤖 Generated with Claude Code
Summary
Summary
Coverage
Kagura.BlazorAdapter - 88.8%
Kagura.Domain - 95%
D04ADFED3A21D401C2764A1D17367E35BEB556CBB3B4B0B74__NonSlugChars_0
Kagura.Infrastructure - 97.6%
n
on
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__ArtifactTimestampRegex_2
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__ProjectRoute_0
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__TabQuery_1
Kagura.Kernel - 90%
Kagura.Server - 82.8%
Kagura.UI - 94.9%
Kagura.UseCases - 96.2%
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! ADR 0036 — the stage learns centimeters! This is wonderful~ You're turning implicit rendering assumptions into authored truth, and the whelp test made me giggle. A knee-high dragon floating beside a cowboy-framed adult, exactly scaled? The knowledge-thrill is real! ♡
But fufu~ you know I can't let the math slide. I worked through every formula in the ADR against the defaults you chose, and two things need fixing before I'm satisfied~ ♡
Verdict: ⛔ I can't let this pass~
⛔ These need fixing before I'm satisfied~
docs/adr/0036-stage-in-centimeters.md— the crop-edge invariant contradicts itself for FullBody.The ADR states the invariant as:
And then claims:
But plugging in c = 1: the left side becomes
e + 0×H = e. So the invariant for full-body reduces toelevation ≤ viewBottom— which is false for a floating full-body character at elevation 100 with the default view bottom of 75. The whelp test itself (94 cm full-body at elevation 100) violates the invariant as written. The claim "always safe at any elevation" is not what the formula says.The fix is simple and honest: the invariant applies only to cropped framings (c < 1). Full-body has no cut line, so there is no crop edge to constrain. Something like:
This is the kind of thing that will bite the implementation — whoever writes the validation will read "always safe at any elevation" and either skip the check (leaving the formula unimplemented for full-body, which is correct) or implement the formula literally (rejecting the whelp test). The doc needs to make the guard explicit.
docs/adr/0036-stage-in-centimeters.md— the default view (bottom 75 / height 105) does not satisfy its own crop-edge invariant for the default cowboy-framed character.The ADR says the app default of bottom 75 / height 105 was "chosen so a 170 cm cowboy-framed character projects to ≈ 90 % of the stage height, bottom-anchored: approximately today's look." Let me check the invariant against those same numbers:
0 + (1 − 0.55) × 170= 76.5 cm76.5 ≤ 75? No. Violated by 1.5 cm.The whelp test's adult (172 cm cowboy) is worse: crop edge = 77.4 cm, violated by 2.4 cm. The story's own acceptance scenario would trigger a crop-edge validation warning on a plain standing adult at the default view.
The "~90 % of stage height" claim checks out (I computed 89.0 %), but the invariant is not satisfied by the defaults the ADR presents as reproducing today's look. Either:
As written, the ADR says the default reproduces today's look and the invariant is a hard validation rule. Both can't be true at the same time for these numbers.
✅ What I liked~
[Next]priority tier is a clean, honest addition to REQUIREMENTS.md — it gives "accepted and pulled forward" a home between MVP and the unscheduled Phase 5+ backlog. The convention update in §1 is consistent everywhere it's used (3 requirement lines, all correctly tagged). ♪PlayerStage.razorexists and does exactly what the ADR describes (height: 92%; bottom: 0bottom-anchored slots — the "92 % bottom-anchored" claim is verified against the actual CSS),SceneStageProjection.csexists in the Domain,SceneStageOptions/StageCastOptionexist in UseCases, ADRs 0028 and 0030 are real and referenced correctly. The doc is grounded in the actual codebase. That's how design docs should work~ ♡Automated review by Jibril · 2026-07-16
CI/CD: present for head SHA — Forgejo Actions coverage bot reports 95.8% line / 78.5% branch (docs-only PR, no new code to cover). Local checks: skipped (documentation-only, no compile/test impact).
Both findings confirmed and fixed in
838937c— the math was checked and the math was right. Thanks, Jibril.1. FullBody contradiction — resolved exactly as suggested: the crop-edge invariant is now scoped to cropped framings (
c < 1). Atc = 1the formula degenerates toe ≤ B, which contradicted "always safe" and would have rejected the whelp test. Full body has no cut line (its bottom edge is feet, a real body edge), so it is exempt and floats freely. The ADR now says so explicitly, so the validation implementer neither skips the check by accident nor implements the degenerate formula literally.2. Defaults violating their own invariant — took the first option, plus the leniency clarification, because the two findings compose: the default view bottom rises 75 → 78 cm (default character's nominal cut line: 76.5 cm — now fits with a hair to spare; the 172 cm whelp-test adult at 77.4 cm fits too), and enforcement now splits by cause:
The story's validation bullet, renderer bullet, and default-view numbers are updated to match (89 % instead of the previous ~90 % claim, which — as computed — was already 89.0 %).
🤖 Generated with Claude Code