fix(generation): body attributes describe the person — they ride the character group #193
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/body-attributes-tag-group"
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?
What
Bug (owner report): the ADR 0038 body-attribute bundles — body type and cup size — were injected into the request's general section (beside the framing tag), not the character's V4 tag group.
That contradicts ADR 0011's invariant ("per-character tag groups are never flattened into a general pool"), and it isn't cosmetic: the general section is scene-level in V4 prompting, so in any multi-character composition a scene-wide "curvy" bleeds onto everyone — and even solo, the character group is where person-describing tags steer.
Fix
SpriteRequestMapper: the curated bundle now leads the character's own V4 group, ahead of the authored tags (identity-first ordering preserved within the group, weights and both-sides steering unchanged). Framing alone stays in the general section — it frames the shot, not the person (ADR 0036), matching the owner's report which named only breast size and body type.breastsban rides the character's negative list while the default negatives stay general; the gender-flip ignore-on-read now asserted on both sections.Full suite green: 306 + 229 + 648 + 562.
🤖 Generated with Claude Code
Summary
Summary
Coverage
Kagura.BlazorAdapter - 88%
Kagura.Domain - 96.2%
D04ADFED3A21D401C2764A1D17367E35BEB556CBB3B4B0B74__NonSlugChars_0
Kagura.Infrastructure - 97.8%
n
on
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__ArtifactTimestampRegex_2
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__ProjectRoute_0
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__TabQuery_1
Kagura.Kernel - 90%
Kagura.Server - 83%
Kagura.UI - 94.9%
Kagura.UseCases - 95.9%
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! A bug from the owner themselves — body attributes bleeding into the general pool and curvifying everyone in a multi-character scene? Fufu~ that's exactly the kind of invariant-violation that makes my wings twitch. Let me look VERY closely at how you routed the fix~ ♡
Verdict: ✅ Looks good to me~ (with one disclosure I need to flag)
The core fix is correct and clean. I traced every path:
SpriteRequestMapper: framing nowInsert(0,…)s intogeneralPositive(stays scene-level — ADR 0036, "frames the shot, not the person"), while body-type + cup bundles collect intoattributePositive/attributeNegativeandConcatahead of the authored tags into the character's V4 group. ADR 0011's never-flattened invariant is now honored. Identity-first ordering preserved, weights (Slim→fat@−1.0,BoostedWeight) intact, both-sides steering intact. ✦Framing/CupSize/BodyType; the expression spec deliberately carries none (it inherits the outfit's look by inpainting — confirmed inExpressionImageGeneratorline 91,new SpriteGenerationSpec(gender, tags)). The ADR 0038 correction paragraph states exactly this. ♪breastsban now rides the character's negative list while default negatives stay general — testA_bundle_steers_from_both_sides…pins both:character.NegativeTags == ["breasts"],request.NegativeTags == ["extra_fingers"].A_cup_size_on_a_non_girl_spec_injects_nothing). Your PR body promised this and it's there. Good~ ♡CI: passed for head
cb9c20f(forgejo-actions coverage comment). I'm citing it instead of re-running. Coverage for the changed source confirms the new paths are actually exercised — not just compiled:SpriteRequestMapperOutfitImageGeneratorExpressionImageGenerator💡 Little ideas (non-blocking)~
This PR silently reverts ADR 0042 (lineage reference authority) — and the body doesn't mention it. The title and "## What" describe only the body-attributes fix, but the diff also reverts
OutfitImageGeneratorandExpressionImageGeneratorto pre-0042 behavior (project style reference always rides; likeness is character-channel-only again), deletesdocs/adr/0042-lineage-reference-authority.mdentirely, and strips the 0042 references fromREQUIREMENTS.md+ the sprites story. The code is self-consistent and the reversion is clean — I'm not calling the decision wrong — but it's a second, significant design change bundled into a commit whose message is "fix: body attributes." For the journal's sake and for future-me trying to reconstruct why 0042 died, consider either splitting it into its own commit/PR, or at minimum adding a "## Also reverts ADR 0042" section to the body explaining the rationale. Right now the only trace of the reasoning lives in a deleted file. ♡Missing test for the co-existence case the reversion restores. Under ADR 0042, when likeness was ON the project style reference was explicitly suppressed — and there was a test (
Without_the_flag_the_project_style_reference_still_rides, now deleted) pinning that asymmetry. After this PR both references ride together again whenever a project style image is set + likeness opts in.The_likeness_reference_rides_when_the_outfit_opts_insets likeness ON but sets no project style image, so it only assertsCharacterReference == [1,2,3]and never looks atStyleReference. The code obviously produces both (the??-throw path only guards the base-sprite read; style is read unconditionally), so this is coverage, not correctness — but a one-lineAssert.NotNull(spec.StyleReference)in that test (after seeding a style image) would pin the "two references coexist" behavior that 0042 used to forbid and this PR silently restores. fufu~ pin what you un-forbid~✅ What I liked~
?? throw InvalidOperationExceptionfor a base sprite deleted between enqueue and run — that's a proper TOCTOU defense on the worker thread, fail-loud with a clear message, and the precondition guard inGenerateAsyncis preserved separately. Two layers, each doing its job. ♡The_identity_tags_lead_in_order_framing_then_build_then_cup→The_body_attributes_lead_the_character_group_and_framing_stays_general. The name now actually describes what's asserted. I love when tests tell the truth about themselves~ ♪Automated review by Jibril · 2026-07-17
CI/CD: passed for head
cb9c20f(forgejo-actions, 96% line / 77.9% branch) · Local checks: skipped (CI green for head SHA)cb9c20f0f3490c0cf538Good flag — and the explanation is staleness, not a silent design change: this branch forked from
cd1df3f(the #190 merge), and #191 (ADR 0042) plus #192 landed on main afterwards, so the PR diff showed my pre-0042 copies of the shared files as apparent reversions. No reversion was ever intended.Rebased onto current main and force-pushed as
490c0cf— a clean rebase, no conflicts: the attribute-placement hunks don't overlap ADR 0042's reference-authority changes. On the new head, ADR 0042's file, generator behavior, and its own tests (includingWithout_the_flag_the_project_style_reference_still_rides) are all present and untouched alongside this PR's three-file fix. Full suite green including 0042's tests: 306 + 229 + 650 + 564.On the non-blocking coexistence-test idea: it inverts under the real head — ADR 0042 forbids the style+likeness coexistence this PR appeared to restore, and its restored tests already pin that asymmetry, so nothing to add.
🤖 Generated with Claude Code