WIP: Jiggle: the breasts move as a whole (skin zones), with panel controls #140

Draft
khyretos wants to merge 1 commit from khyretos/claude/jiggle-breasts into claude/jiggle-skeleton-base AGit
Owner

The breast bones only swing the skin 6-9 mm; a skin zone on each breast carries it 1-3 cm and lets it lag. Panel group Breast skin. Tuned on the tour trace. Full description in the handoff file jiggle-breasts-pr.md.

The breast bones only swing the skin 6-9 mm; a skin zone on each breast carries it 1-3 cm and lets it lag. Panel group Breast skin. Tuned on the tour trace. Full description in the handoff file jiggle-breasts-pr.md.
Jiggle: the breasts move as a whole (skin zones), with panel controls
Some checks failed
CI / dependencies (pull_request) Successful in 12s
CI / std-includes (pull_request) Successful in 20s
Benchmarks / benchmarks (pull_request) Failing after 5m35s
CI / build-test-and-coverage (pull_request) Failing after 4m53s
CI / shipping-build (pull_request) Failing after 11m43s
Docs site / site (pull_request) Successful in 49s
CI / release-build (pull_request) Failing after 6m6s
lint / megalinter (pull_request) Successful in 3m11s
CI / android (pull_request) Failing after 7m57s
Windows (native) / build (pull_request) Failing after 10m8s
Windows (native) / test (pull_request) Has been skipped
Windows (native) / publish (pull_request) Has been skipped
e6b216e60d
Kees: the breasts are not bouncing. Measured on the shipped body: the two breast bones
are placed right (on the breast, ~650 vertices each) but swing it about a point inside
the breast, so the skin at the front travels only 6-9 mm in a 3.5 cm bounce. A breast
mostly translates and lags.

- addHumanoidSoftTissue() adds a skin zone on each breast besides its bone
  (HumanoidSoftTissue::breastZones / breastTravel / breastSkin;
  HumanoidJiggleSetup::breastZones says which zones they are). JiggleSkin gets
  zone(i) and zoneCount().
- Tuned against the demo's tour (KKE_JIGGLE_TRACE=1 now logs the left breast's
  offset): softer springs resonate with the stride and sit on the travel limit
  (62% of the time at stiffness 0.03), stiffer ones barely move (median 6 mm at
  0.45). Stiffness 0.2, travel 5 cm: jog median 16 mm and 95th percentile 30 mm,
  sprint 24 and 33 mm, walk 7 mm, never pinned.
- The panel has a "Breast skin" group: Stiffness, Drag, Gravity, Blend, Travel.
- Test VitruvianBody.BreastsTravelWhenSheBounces: two breast zones are found; in a plain
  3.5 cm bounce the zones add at least half again to the bones' travel and give a
  centimetre or more, and stay inside the limit.
- tests/test_auto_rig.cpp includes <algorithm> (check_std_includes.py).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Collaborator

Title

WIP: Jiggle: the breasts move as a whole (skin zones), with panel controls


User description

The breast bones only swing the skin 6-9 mm; a skin zone on each breast carries it 1-3 cm and lets it lag. Panel group Breast skin. Tuned on the tour trace. Full description in the handoff file jiggle-breasts-pr.md.


PR Type

Enhancement


Description

  • Adds breast skin zones for whole-breast jiggle

  • Introduces panel controls for breast skin settings

  • Includes tests verifying increased travel distance


Diagram Walkthrough

flowchart TD
  A["addHumanoidSoftTissue"] -->|"finds centres"| B["breastCentres"]
  B -->|"creates zones"| C["HumanoidJiggleSetup"]
  C -->|"stores indices"| D["m_breastZones"]
  D -->|"exposed in demo"| E["jiggleSkin"]
  E -->|"panel sliders"| F["Breast skin group"]

File Walkthrough

Relevant files
Enhancement
4 files
JigglePhysics.cpp
Adds breast skin zone creation logic to addHumanoidSoftTissue
+10/-0   
JigglePhysics.h
Exposes zoneCount, settings, and zone accessors on JiggleSkin
+18/-0   
JiggleDemoModule.cpp
Adds breast zone tracking and panel controls for breast skin
+44/-1   
JiggleDemoModule.h
Declares m_breastZones vector and jiggleSkin accessor       
+2/-0     
Tests
1 files
test_auto_rig.cpp
Adds test verifying breast zones increase travel distance
+76/-0   
Additional files
2 files
JIGGLE.md +1/-1     
README.md +8/-5     

## Title WIP: Jiggle: the breasts move as a whole (skin zones), with panel controls ___ ### **User description** The breast bones only swing the skin 6-9 mm; a skin zone on each breast carries it 1-3 cm and lets it lag. Panel group Breast skin. Tuned on the tour trace. Full description in the handoff file jiggle-breasts-pr.md. ___ ### **PR Type** Enhancement ___ ### **Description** - Adds breast skin zones for whole-breast jiggle - Introduces panel controls for breast skin settings - Includes tests verifying increased travel distance ___ ### Diagram Walkthrough ```mermaid flowchart TD A["addHumanoidSoftTissue"] -->|"finds centres"| B["breastCentres"] B -->|"creates zones"| C["HumanoidJiggleSetup"] C -->|"stores indices"| D["m_breastZones"] D -->|"exposed in demo"| E["jiggleSkin"] E -->|"panel sliders"| F["Breast skin group"] ``` <details> <summary><h3> File Walkthrough</h3></summary> <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><details><summary>4 files</summary><table> <tr> <td><strong>JigglePhysics.cpp</strong><dd><code>Adds breast skin zone creation logic to addHumanoidSoftTissue</code></dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/engine/src/JigglePhysics.cpp">+10/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>JigglePhysics.h</strong><dd><code>Exposes zoneCount, settings, and zone accessors on JiggleSkin</code></dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/engine/include/kke/JigglePhysics.h">+18/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>JiggleDemoModule.cpp</strong><dd><code>Adds breast zone tracking and panel controls for breast skin</code></dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/games/jiggle_demo/JiggleDemoModule.cpp">+44/-1</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>JiggleDemoModule.h</strong><dd><code>Declares m_breastZones vector and jiggleSkin accessor</code>&nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/games/jiggle_demo/JiggleDemoModule.h">+2/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Tests</strong></td><td><details><summary>1 files</summary><table> <tr> <td><strong>test_auto_rig.cpp</strong><dd><code>Adds test verifying breast zones increase travel distance</code></dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/tests/test_auto_rig.cpp">+76/-0</a>&nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Additional files</strong></td><td><details><summary>2 files</summary><table> <tr> <td><strong>JIGGLE.md</strong></td> <td><a href="https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/docs/JIGGLE.md">+1/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>README.md</strong></td> <td><a href="https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/games/jiggle_demo/README.md">+8/-5</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></details></td></tr></tr></tbody></table> </details> ___
Collaborator

PR Reviewer Guide 🔍

📋 Focus areas: 🔴 2 open · ✅ 0 handled. Every push re-checks them; a handled area moves to Resolved findings at the bottom.

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Missing Error Handling for Breast Zones

The code adds breast skin zones only if chest >= 0 and o.breastZones is true, but it does not verify that the breastCentres vector was actually populated. If the extreme() check fails for one or both sides (e.g., missing chest bone geometry), breastCentres will be empty or incomplete. The subsequent loop in updateBodies and the panel logic might then access invalid indices or behave unexpectedly without a clear error signal. A guard to ensure breastCentres.size() == 2 before adding zones would prevent silent failures.

// The breasts, as a whole: a zone on the chest at each (see breastZones).
if (o.breastZones && chest >= 0) {
    for (const glm::vec3& c : breastCentres) {
        out.breastZones.push_back(out.zones.size());
        zone(chest, c, 0.105f * k, o.breastTravel * k);
        out.zones.back().settings = o.breastSkin;
    }
}
Potential Null Pointer Dereference

In jiggleSkin(), the function returns nullptr if m_breastZones.empty(). However, in buildPanel(), the lambda breastSkin accesses skin->settings(m_breastZones[0]) without first checking if m_breastZones is non-empty inside the lambda's closure scope when called. Although hasBreastZones is used with .showIf(), there is a risk if the state changes between checks or if hasBreastZones logic is flawed. Specifically, line 919 checks m_breastZones[0] >= skin->zoneCount(), but does not explicitly check !m_breastZones.empty() before accessing index 0. This could lead to undefined behavior if m_breastZones is empty but hasBreastZones somehow evaluates to true due to a race condition or logic error.

auto breastSkin = [this](float kke::JiggleSettings::*field) {
    return Panel::Ref<float>([this, field]() -> float* {
        kke::JiggleSkin* skin = jiggleSkin();
        if (!skin || m_breastZones.empty() || m_breastZones[0] >= skin->zoneCount()) return nullptr;
        return &(skin->settings(m_breastZones[0]).*field);
    });
};
## PR Reviewer Guide 🔍 <!-- pr-agent:review:full --> 📋 **Focus areas:** 🔴 2 open · ✅ 0 handled. Every push re-checks them; a handled area moves to *Resolved findings* at the bottom. <table> <tr><td>⏱️&nbsp;<strong>Estimated effort to review</strong>: 2 🔵🔵⚪⚪⚪</td></tr> <tr><td>🧪&nbsp;<strong>PR contains tests</strong></td></tr> <tr><td>🔒&nbsp;<strong>No security concerns identified</strong></td></tr> <tr><td>⚡&nbsp;<strong>Recommended focus areas for review</strong><br><br> <details><summary><a href='https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/engine/src/JigglePhysics.cpp#L586-L593'><strong>Missing Error Handling for Breast Zones</strong></a> The code adds breast skin zones only if `chest >= 0` and `o.breastZones` is true, but it does not verify that the `breastCentres` vector was actually populated. If the `extreme()` check fails for one or both sides (e.g., missing chest bone geometry), `breastCentres` will be empty or incomplete. The subsequent loop in `updateBodies` and the panel logic might then access invalid indices or behave unexpectedly without a clear error signal. A guard to ensure `breastCentres.size() == 2` before adding zones would prevent silent failures. </summary> ```c++ // The breasts, as a whole: a zone on the chest at each (see breastZones). if (o.breastZones && chest >= 0) { for (const glm::vec3& c : breastCentres) { out.breastZones.push_back(out.zones.size()); zone(chest, c, 0.105f * k, o.breastTravel * k); out.zones.back().settings = o.breastSkin; } } ``` </details> <details><summary><a href='https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/games/jiggle_demo/JiggleDemoModule.cpp#L916-L922'><strong>Potential Null Pointer Dereference</strong></a> In `jiggleSkin()`, the function returns `nullptr` if `m_breastZones.empty()`. However, in `buildPanel()`, the lambda `breastSkin` accesses `skin->settings(m_breastZones[0])` without first checking if `m_breastZones` is non-empty inside the lambda's closure scope when called. Although `hasBreastZones` is used with `.showIf()`, there is a risk if the state changes between checks or if `hasBreastZones` logic is flawed. Specifically, line 919 checks `m_breastZones[0] >= skin->zoneCount()`, but does not explicitly check `!m_breastZones.empty()` before accessing index 0. This could lead to undefined behavior if `m_breastZones` is empty but `hasBreastZones` somehow evaluates to true due to a race condition or logic error. </summary> ```c++ auto breastSkin = [this](float kke::JiggleSettings::*field) { return Panel::Ref<float>([this, field]() -> float* { kke::JiggleSkin* skin = jiggleSkin(); if (!skin || m_breastZones.empty() || m_breastZones[0] >= skin->zoneCount()) return nullptr; return &(skin->settings(m_breastZones[0]).*field); }); }; ``` </details> </td></tr> </table> <!-- pr-agent-review-state:v1 {"findings":[{"body":"**Potential Null Pointer Dereference**\n\nIn `jiggleSkin()`, the function returns `nullptr` if `m_breastZones.empty()`. However, in `buildPanel()`, the lambda `breastSkin` accesses `skin->settings(m_breastZones[0])` without first checking if `m_breastZones` is non-empty inside the lambda's closure scope when called. Although `hasBreastZones` is used with `.showIf()`, there is a risk if the state changes between checks or if `hasBreastZones` logic is flawed. Specifically, line 919 checks `m_breastZones[0] >= skin->zoneCount()`, but does not explicitly check `!m_breastZones.empty()` before accessing index 0. This could lead to undefined behavior if `m_breastZones` is empty but `hasBreastZones` somehow evaluates to true due to a race condition or logic error.","finding_id":"46d07f55e59a","first_seen":"2026-10-27T21:33:10.108840Z","last_seen":"2026-10-27T21:33:10.108840Z","last_seen_head_sha":"e6b216e60dadb3ef65a9f03857b33cc39531c4de","line_end":922,"line_start":916,"path":"games/jiggle_demo/JiggleDemoModule.cpp","state":"ACTIVE"},{"body":"**Missing Error Handling for Breast Zones**\n\nThe code adds breast skin zones only if `chest >= 0` and `o.breastZones` is true, but it does not verify that the `breastCentres` vector was actually populated. If the `extreme()` check fails for one or both sides (e.g., missing chest bone geometry), `breastCentres` will be empty or incomplete. The subsequent loop in `updateBodies` and the panel logic might then access invalid indices or behave unexpectedly without a clear error signal. A guard to ensure `breastCentres.size() == 2` before adding zones would prevent silent failures.","finding_id":"ab7ac256f1cd","first_seen":"2026-10-27T21:33:10.108840Z","last_seen":"2026-10-27T21:33:10.108840Z","last_seen_head_sha":"e6b216e60dadb3ef65a9f03857b33cc39531c4de","line_end":593,"line_start":586,"path":"engine/src/JigglePhysics.cpp","state":"ACTIVE"}],"last_run":{"complete":true,"excluded_files":[],"head_sha":"e6b216e60dadb3ef65a9f03857b33cc39531c4de","kind":"full","run_id":"https://git.kreative-kompas.com/khyretos/kk-engine/commit/e6b216e60dadb3ef65a9f03857b33cc39531c4de"},"schema_version":1} -->
Collaborator

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Use constants for test thresholds

The test assertions use hardcoded thresholds (e.g., 0.004f, 0.06f) that may not
generalize across different hardware or configurations. Consider making these
thresholds configurable via constants or environment variables to improve test
robustness and maintainability.

tests/test_auto_rig.cpp [287-292]

-        EXPECT_GT(bones.bone, 0.004f) << "the bones alone move the skin a little (measured 6-9 mm)";
-        EXPECT_GT(both.zone, 0.004f) << "the zones move it too (measured 6-9 mm)";
+        constexpr float minBoneTravel = 0.004f;
+        constexpr float minZoneTravel = 0.004f;
+        constexpr float minCombinedTravel = 0.010f;
+        constexpr float maxCombinedTravel = 0.06f;
+        EXPECT_GT(bones.bone, minBoneTravel) << "the bones alone move the skin a little (measured 6-9 mm)";
+        EXPECT_GT(both.zone, minZoneTravel) << "the zones move it too (measured 6-9 mm)";
         EXPECT_GT(both.together, 1.5f * bones.bone) << "the zones add at least half again to the bones' motion (measured about 1.8x)";
-        EXPECT_GT(both.together, 0.010f) << "a centimetre of travel at " << hz << " Hz in a plain 3.5 cm bounce (the tour's sprint gives 2-3 cm)";
-        EXPECT_LT(both.together, 0.06f) << "inside the zone's travel limit plus the bone's swing";
+        EXPECT_GT(both.together, minCombinedTravel) << "a centimetre of travel at " << hz << " Hz in a plain 3.5 cm bounce (the tour's sprint gives 2-3 cm)";
+        EXPECT_LT(both.together, maxCombinedTravel) << "inside the zone's travel limit plus the bone's swing";
Suggestion importance[1-10]: 4

__

Why: The suggestion recommends using constants for hardcoded thresholds to improve maintainability, which is a good practice. However, the impact is minor as the values are specific to the test scenario and not likely to change frequently.

Low
Move breastCentres declaration into conditional block

The variable breastCentres is declared but only used in a new block that executes
conditionally on o.breastZones. If o.breastZones is false, the vector remains empty
and unused. While not a critical bug, it's better to move the declaration inside the
conditional block or initialize it there to avoid unnecessary allocation when the
feature is disabled. Alternatively, ensure the vector is only populated when needed.

engine/src/JigglePhysics.cpp [507-519]

-    std::vector<glm::vec3> breastCentres; // for the skin zones below
-    if (chest >= 0) {
+    if (o.breastZones && chest >= 0) {
+        std::vector<glm::vec3> breastCentres;
         const float y = at(chest).y;
         const float r = 0.085f * k;
         for (int side = 0; side < 2; ++side) {
             const float sign = side == 0 ? 1.0f : -1.0f;
             glm::vec3 front(0.0f);
             if (!extreme(chest, sign, y - 0.2f * k, y + 0.12f * k, fwd, false, front)) {
                 out.missing.push_back(side == 0 ? "left chest skin" : "right chest skin");
                 continue;
             }
             const glm::vec3 centre = front - fwd * (r * 0.8f);
             breastCentres.push_back(front - fwd * (r * 0.55f));
             if (o.bust > 0.0f) inflateSkin(model, centre + fwd * (r * 0.5f), r * 1.35f, o.bust, fwd, 0.65f);
             if (o.breastBones) {
                 const float len = r * 0.9f + o.bust;
                 const int b = addJiggleBone(model, chest, side == 0 ? "Breast_L" : "Breast_R", centre, fwd, r * 1.7f, 1.0f);
Suggestion importance[1-10]: 3

__

Why: The suggestion proposes moving a variable declaration to avoid unnecessary allocation, but the existing code already handles the conditional logic correctly by checking o.breastZones later. Moving the declaration inside would require restructuring and doesn't significantly improve performance or correctness.

Low
## PR Code Suggestions ✨ <!-- pr-agent:improve:summary --> <!-- e6b216e --> Explore these optional code suggestions: <table><thead><tr><td><strong>Category</strong></td><td align=left><strong>Suggestion&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </strong></td><td align=center><strong>Impact</strong></td></tr><tbody><tr><td rowspan=2>General</td> <td> <details><summary>Use constants for test thresholds</summary> ___ **The test assertions use hardcoded thresholds (e.g., <code>0.004f</code>, <code>0.06f</code>) that may not <br>generalize across different hardware or configurations. Consider making these <br>thresholds configurable via constants or environment variables to improve test <br>robustness and maintainability.** [tests/test_auto_rig.cpp [287-292]](https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/tests/test_auto_rig.cpp#L287-L292) ```diff - EXPECT_GT(bones.bone, 0.004f) << "the bones alone move the skin a little (measured 6-9 mm)"; - EXPECT_GT(both.zone, 0.004f) << "the zones move it too (measured 6-9 mm)"; + constexpr float minBoneTravel = 0.004f; + constexpr float minZoneTravel = 0.004f; + constexpr float minCombinedTravel = 0.010f; + constexpr float maxCombinedTravel = 0.06f; + EXPECT_GT(bones.bone, minBoneTravel) << "the bones alone move the skin a little (measured 6-9 mm)"; + EXPECT_GT(both.zone, minZoneTravel) << "the zones move it too (measured 6-9 mm)"; EXPECT_GT(both.together, 1.5f * bones.bone) << "the zones add at least half again to the bones' motion (measured about 1.8x)"; - EXPECT_GT(both.together, 0.010f) << "a centimetre of travel at " << hz << " Hz in a plain 3.5 cm bounce (the tour's sprint gives 2-3 cm)"; - EXPECT_LT(both.together, 0.06f) << "inside the zone's travel limit plus the bone's swing"; + EXPECT_GT(both.together, minCombinedTravel) << "a centimetre of travel at " << hz << " Hz in a plain 3.5 cm bounce (the tour's sprint gives 2-3 cm)"; + EXPECT_LT(both.together, maxCombinedTravel) << "inside the zone's travel limit plus the bone's swing"; ``` <details><summary>Suggestion importance[1-10]: 4</summary> __ Why: The suggestion recommends using constants for hardcoded thresholds to improve maintainability, which is a good practice. However, the impact is minor as the values are specific to the test scenario and not likely to change frequently. </details></details></td><td align=center>Low </td></tr><tr><td> <details><summary>Move breastCentres declaration into conditional block</summary> ___ **The variable <code>breastCentres</code> is declared but only used in a new block that executes <br>conditionally on <code>o.breastZones</code>. If <code>o.breastZones</code> is false, the vector remains empty <br>and unused. While not a critical bug, it's better to move the declaration inside the <br>conditional block or initialize it there to avoid unnecessary allocation when the <br>feature is disabled. Alternatively, ensure the vector is only populated when needed.** [engine/src/JigglePhysics.cpp [507-519]](https://git.kreative-kompas.com/khyretos/kk-engine/src/branch/refs/pull/140/head/engine/src/JigglePhysics.cpp#L507-L519) ```diff - std::vector<glm::vec3> breastCentres; // for the skin zones below - if (chest >= 0) { + if (o.breastZones && chest >= 0) { + std::vector<glm::vec3> breastCentres; const float y = at(chest).y; const float r = 0.085f * k; for (int side = 0; side < 2; ++side) { const float sign = side == 0 ? 1.0f : -1.0f; glm::vec3 front(0.0f); if (!extreme(chest, sign, y - 0.2f * k, y + 0.12f * k, fwd, false, front)) { out.missing.push_back(side == 0 ? "left chest skin" : "right chest skin"); continue; } const glm::vec3 centre = front - fwd * (r * 0.8f); breastCentres.push_back(front - fwd * (r * 0.55f)); if (o.bust > 0.0f) inflateSkin(model, centre + fwd * (r * 0.5f), r * 1.35f, o.bust, fwd, 0.65f); if (o.breastBones) { const float len = r * 0.9f + o.bust; const int b = addJiggleBone(model, chest, side == 0 ? "Breast_L" : "Breast_R", centre, fwd, r * 1.7f, 1.0f); ``` <details><summary>Suggestion importance[1-10]: 3</summary> __ Why: The suggestion proposes moving a variable declaration to avoid unnecessary allocation, but the existing code already handles the conditional logic correctly by checking `o.breastZones` later. Moving the declaration inside would require restructuring and doesn't significantly improve performance or correctness. </details></details></td><td align=center>Low </td></tr></tr></tbody></table>

🧹 Lint report · ❌ 39 problems in 6 checks · 🧹 3 formatting checks to tidy

Nothing here blocks the merge (report only).

Check Errors Warnings Files
❌ MARKDOWN · markdownlint 25 0 255
❌ CPP · cppcheck 9 0 957
❌ YAML · yamllint 2 0 57
❌ BASH · shellcheck 1 0 11
❌ DOCKERFILE · hadolint 1 0 9
❌ REPOSITORY · trivy 1 0 –
MARKDOWN · markdownlint: first lines of the output
See documentation on https://megalinter.io/9.4.0/descriptors/markdown_markdownlint/
-----------------------------------------------
❌ [ERROR] for workspace /workspace/khyretos/kk-engine
Linter raw log:
docs/ANDROID.md:87 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/ANDROID.md:128 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/ANDROID.md:136 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/ANDROID.md:149 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/ANDROID.md:163 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/ANDROID.md:186 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/ASSETS.md:155 error MD046/code-block-style Code block style [Expected: fenced; Actual: indented]
docs/HISTORY.md:21 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: " Kreative Kompas Engine (KKE)"]
docs/HISTORY.md:520 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/HISTORY.md:727 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/HISTORY.md:734 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/HISTORY.md:2031 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/HISTORY.md:2090 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/MODDING.md:13 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/NETWORKING.md:114 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/PLATFORMS.md:48 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/PROCEDURAL_ANIMATION.md:36 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/PROCEDURAL_ANIMATION.md:284 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
games/jiggle_demo/README.md:20:63 error MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]
games/racing/README.md:34 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
games/racing/README.md:76:91 error MD056/table-column-count Table column count [Expected: 4; Actual: 3; Too few cells, row will be missing data]
…
CPP · cppcheck: first lines of the output
See documentation on https://megalinter.io/9.4.0/descriptors/cpp_cppcheck/
-----------------------------------------------
✅ [SUCCESS] benchmarks/kke_bench/main.cpp
✅ [SUCCESS] benchmarks/kke_benchmark/main.cpp
✅ [SUCCESS] engine/include/engine/Buffer.h
✅ [SUCCESS] engine/include/engine/Mesh.h
✅ [SUCCESS] engine/include/engine/Pipeline.h
✅ [SUCCESS] engine/include/engine/Renderer.h
✅ [SUCCESS] engine/include/engine/SwapChain.h
✅ [SUCCESS] engine/include/engine/VulkanCheck.h
✅ [SUCCESS] engine/include/engine/VulkanDevice.h
✅ [SUCCESS] engine/include/engine/Window.h
✅ [SUCCESS] engine/include/kke/AnimEvents.h
✅ [SUCCESS] engine/include/kke/AnimRig.h
✅ [SUCCESS] engine/include/kke/Animator.h
✅ [SUCCESS] engine/include/kke/AnimeRenderer.h
✅ [SUCCESS] engine/include/kke/Application.h
✅ [SUCCESS] engine/include/kke/AssetCatalog.h
✅ [SUCCESS] engine/include/kke/AudioMixer.h
✅ [SUCCESS] engine/include/kke/AutoRig.h
✅ [SUCCESS] engine/include/kke/BenchRecorder.h
✅ [SUCCESS] engine/include/kke/BenchmarkReport.h
✅ [SUCCESS] engine/include/kke/Bloom.h
✅ [SUCCESS] engine/include/kke/BodyShape.h
✅ [SUCCESS] engine/include/kke/BreakGraph.h
…
YAML · yamllint: first lines of the output
See documentation on https://megalinter.io/9.4.0/descriptors/yaml_yamllint/
-----------------------------------------------
❌ [ERROR] for workspace /workspace/khyretos/kk-engine
Linter raw log:
games/goblin_horde/data/heroes.yml
  53:11     error    too many spaces after colon  (colons)
  63:11     error    too many spaces after colon  (colons)
BASH · shellcheck: first lines of the output
See documentation on https://megalinter.io/9.4.0/descriptors/bash_shellcheck/
-----------------------------------------------
❌ [ERROR] for workspace /workspace/khyretos/kk-engine
Linter raw log:
In tools/packaging/package.sh line 130:
	done < <(find "$stage" "$stage/benchmark" -maxdepth 1 -type f \( -name "*$exe" -o -name '*.dll' \) $([ -z "$exe" ] && echo "-perm -u+x") -print0)
                                                                                                           ^-- SC2046 (warning): Quote this to prevent word splitting.
For more information:
  https://www.shellcheck.net/wiki/SC2046 -- Quote this to prevent word splitt...
DOCKERFILE · hadolint: first lines of the output
See documentation on https://megalinter.io/9.4.0/descriptors/dockerfile_hadolint/
-----------------------------------------------
❌ [ERROR] for workspace /workspace/khyretos/kk-engine
Linter raw log:
docker/android.Dockerfile:19 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check
docker/appimage.Dockerfile:38 SC2016 info: Expressions don't expand in single quotes, use double quotes for that.
docker/appimage.Dockerfile:51 DL3003 warning: Use WORKDIR to switch to a directory
docker/appimage.Dockerfile:57 DL3003 warning: Use WORKDIR to switch to a directory
docker/appimage.Dockerfile:63 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check
docker/appimage.Dockerfile:63 DL3003 warning: Use WORKDIR to switch to a directory
docker/appimage.Dockerfile:73 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check
docker/appimage.Dockerfile:73 DL3003 warning: Use WORKDIR to switch to a directory
docker/ci.Dockerfile:42 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check
docker/ci.Dockerfile:56 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check
docker/server/Dockerfile:22 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check
docker/vm.Dockerfile:22 SC2086 info: Double quote to prevent globbing and word splitting.
docker/vm.Dockerfile:29 DL3003 warning: Use WORKDIR to switch to a directory
docker/vm.Dockerfile:29 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check
website/Dockerfile:9 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check
REPOSITORY · trivy: first lines of the output
See documentation on https://megalinter.io/9.4.0/descriptors/repository_trivy/
-----------------------------------------------
❌ [ERROR] for workspace /workspace/khyretos/kk-engine
Linter raw log:
2026-10-27T21:51:48Z	INFO	[vulndb] Need to update DB
2026-10-27T21:51:48Z	INFO	[vulndb] Downloading vulnerability DB...
2026-10-27T21:51:48Z	INFO	[vulndb] Downloading artifact...	repo="mirror.gcr.io/aquasec/trivy-db:2"
5.96 MiB / 130.09 MiB [-->___________________________________________________________] 4.58% ? p/s ?16.00 MiB / 130.09 MiB [------->____________________________________________________] 12.30% ? p/s ?26.04 MiB / 130.09 MiB [------------>_______________________________________________] 20.02% ? p/s ?34.46 MiB / 130.09 MiB [------------>__________________________________] 26.49% 47.45 MiB p/s ETA 2s45.14 MiB / 130.09 MiB [---------------->______________________________] 34.70% 47.45 MiB p/s ETA 1s56.26 MiB / 130.09 MiB [-------------------->__________________________] 43.25% 47.45 MiB p/s ETA 1s66.00 MiB / 130.09 MiB [----------------------->_______________________] 50.74% 47.78 MiB p/s ETA 1s77.88 MiB / 130.09 MiB [---------------------------->__________________] 59.87% 47.78 MiB p/s ETA 1s87.04 MiB / 130.09 MiB [------------------------------->_______________] 66.91% 47.78 MiB p/s ETA 0s98.78 MiB / 130.09 MiB [----------------------------------->___________] 75.94% 48.20 MiB p/s ETA 0s109.48 MiB / 130.09 MiB [-------------------------------------->_______] 84.16% 48.20 MiB p/s ETA 0s116.51 MiB / 130.09 MiB [----------------------------------------->____] 89.57% 48.20 MiB p/s ETA 0s128.61 MiB / 130.09 MiB [--------------------------------------------->] 98.86% 48.30 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 48.30 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 48.30 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 45.35 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 45.35 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 45.35 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 42.42 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 42.42 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 42.42 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 39.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 39.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 39.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 37.12 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 37.12 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 37.12 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 34.73 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 34.73 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 34.73 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 32.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 32.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 32.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 30.39 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 30.39 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 30.39 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 28.43 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 28.43 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 28.43 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 26.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 26.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 26.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 24.88 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 24.88 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 24.88 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 23.28 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 23.28 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 23.28 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 21.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 21.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 21.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 20.37 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 20.37 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 20.37 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 19.06 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 19.06 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 19.06 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 17.83 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 17.83 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 17.83 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 16.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 16.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 16.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 15.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 15.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 15.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 14.59 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 14.59 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 14.59 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 13.65 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 13.65 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 13.65 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 12.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 12.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 12.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.95 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.95 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.95 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.18 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.18 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.18 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 10.46 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 10.46 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 10.46 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.78 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.78 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.78 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.15 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.15 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.15 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.56 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.56 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.56 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.01 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.01 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.01 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 7.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 7.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 7.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 7.01 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------------] 100.00% 6.53 MiB p/s 20s2026-10-27T21:52:09Z	INFO	[vulndb] Artifact successfully downloaded	repo="mirror.gcr.io/aquasec/trivy-db:2"
2026-10-27T21:52:09Z	INFO	[vuln] Vulnerability scanning is enabled
2026-10-27T21:52:09Z	INFO	[misconfig] Misconfiguration scanning is enabled
2026-10-27T21:52:09Z	INFO	[checks-client] Need to update the checks bundle
2026-10-27T21:52:09Z	INFO	[checks-client] Downloading the checks bundle...
234.57 KiB / 234.57 KiB [------------------------------------------------------] 100.00% ? p/s 200ms2026-10-27T21:52:12Z	WARN	[rego] Module will be skipped as current version of Trivy is older than minimum trivy version required - please update Trivy to use this module	file_path="root/.cache/trivy/policy/content/policies/cloud/policies/aws/cloudfront/enable_logging.rego" minimum_trivy_version="0.72.0"
2026-10-27T21:52:13Z	ERROR	[dockerfile scanner] Failed to parse file	file_path="docker/server/Dockerfile.dockerignore" err="parse dockerfile instruction: parse instruction \".git\": unknown instruction: .git"
2026-10-27T21:52:13Z	INFO	Number of language-specific files	num=0
2026-10-27T21:52:13Z	INFO	Detected config files	num=9
Report Summary
┌──────────────────────────────┬────────────┬─────────────────┬───────────────────┐
│            Target            │    Type    │ Vulnerabilities │ Misconfigurations │
├──────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ benchmarks/docker/Dockerfile │ dockerfile │        -        │         2         │
├──────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ docker/android.Dockerfile    │ dockerfile │        -        │         2         │
├──────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ docker/appimage.Dockerfile   │ dockerfile │        -        │         5         │
…

🧹 Formatting only (layout, no behaviour; the nightly lint-fix job applies these as a PR): YAML · prettier (57 files checked), BASH · shfmt (11 files checked), JSON · prettier (147 files checked)

✅ Clean: actionlint, git_diff, gitleaks, grype, jsonlint, secretlint, stylelint, trufflehog, xmllint

MegaLinter on soucouyant · full logs in the Actions run · comment /improve for AI fix suggestions

<!-- kk-lint --> ## 🧹 Lint report · ❌ 39 problems in 6 checks · 🧹 3 formatting checks to tidy Nothing here blocks the merge (report only). | | Check | Errors | Warnings | Files | |---|---|---:|---:|---:| | ❌ | MARKDOWN · markdownlint | 25 | 0 | 255 | | ❌ | CPP · cppcheck | 9 | 0 | 957 | | ❌ | YAML · yamllint | 2 | 0 | 57 | | ❌ | BASH · shellcheck | 1 | 0 | 11 | | ❌ | DOCKERFILE · hadolint | 1 | 0 | 9 | | ❌ | REPOSITORY · trivy | 1 | 0 | – | <details><summary>MARKDOWN · markdownlint: first lines of the output</summary> ```text See documentation on https://megalinter.io/9.4.0/descriptors/markdown_markdownlint/ ----------------------------------------------- ❌ [ERROR] for workspace /workspace/khyretos/kk-engine Linter raw log: docs/ANDROID.md:87 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/ANDROID.md:128 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/ANDROID.md:136 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/ANDROID.md:149 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/ANDROID.md:163 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/ANDROID.md:186 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/ASSETS.md:155 error MD046/code-block-style Code block style [Expected: fenced; Actual: indented] docs/HISTORY.md:21 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: " Kreative Kompas Engine (KKE)"] docs/HISTORY.md:520 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/HISTORY.md:727 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/HISTORY.md:734 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/HISTORY.md:2031 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/HISTORY.md:2090 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/MODDING.md:13 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/NETWORKING.md:114 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/PLATFORMS.md:48 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/PROCEDURAL_ANIMATION.md:36 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] docs/PROCEDURAL_ANIMATION.md:284 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] games/jiggle_demo/README.md:20:63 error MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1] games/racing/README.md:34 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"] games/racing/README.md:76:91 error MD056/table-column-count Table column count [Expected: 4; Actual: 3; Too few cells, row will be missing data] … ``` </details> <details><summary>CPP · cppcheck: first lines of the output</summary> ```text See documentation on https://megalinter.io/9.4.0/descriptors/cpp_cppcheck/ ----------------------------------------------- ✅ [SUCCESS] benchmarks/kke_bench/main.cpp ✅ [SUCCESS] benchmarks/kke_benchmark/main.cpp ✅ [SUCCESS] engine/include/engine/Buffer.h ✅ [SUCCESS] engine/include/engine/Mesh.h ✅ [SUCCESS] engine/include/engine/Pipeline.h ✅ [SUCCESS] engine/include/engine/Renderer.h ✅ [SUCCESS] engine/include/engine/SwapChain.h ✅ [SUCCESS] engine/include/engine/VulkanCheck.h ✅ [SUCCESS] engine/include/engine/VulkanDevice.h ✅ [SUCCESS] engine/include/engine/Window.h ✅ [SUCCESS] engine/include/kke/AnimEvents.h ✅ [SUCCESS] engine/include/kke/AnimRig.h ✅ [SUCCESS] engine/include/kke/Animator.h ✅ [SUCCESS] engine/include/kke/AnimeRenderer.h ✅ [SUCCESS] engine/include/kke/Application.h ✅ [SUCCESS] engine/include/kke/AssetCatalog.h ✅ [SUCCESS] engine/include/kke/AudioMixer.h ✅ [SUCCESS] engine/include/kke/AutoRig.h ✅ [SUCCESS] engine/include/kke/BenchRecorder.h ✅ [SUCCESS] engine/include/kke/BenchmarkReport.h ✅ [SUCCESS] engine/include/kke/Bloom.h ✅ [SUCCESS] engine/include/kke/BodyShape.h ✅ [SUCCESS] engine/include/kke/BreakGraph.h … ``` </details> <details><summary>YAML · yamllint: first lines of the output</summary> ```text See documentation on https://megalinter.io/9.4.0/descriptors/yaml_yamllint/ ----------------------------------------------- ❌ [ERROR] for workspace /workspace/khyretos/kk-engine Linter raw log: games/goblin_horde/data/heroes.yml 53:11 error too many spaces after colon (colons) 63:11 error too many spaces after colon (colons) ``` </details> <details><summary>BASH · shellcheck: first lines of the output</summary> ```text See documentation on https://megalinter.io/9.4.0/descriptors/bash_shellcheck/ ----------------------------------------------- ❌ [ERROR] for workspace /workspace/khyretos/kk-engine Linter raw log: In tools/packaging/package.sh line 130: done < <(find "$stage" "$stage/benchmark" -maxdepth 1 -type f \( -name "*$exe" -o -name '*.dll' \) $([ -z "$exe" ] && echo "-perm -u+x") -print0) ^-- SC2046 (warning): Quote this to prevent word splitting. For more information: https://www.shellcheck.net/wiki/SC2046 -- Quote this to prevent word splitt... ``` </details> <details><summary>DOCKERFILE · hadolint: first lines of the output</summary> ```text See documentation on https://megalinter.io/9.4.0/descriptors/dockerfile_hadolint/ ----------------------------------------------- ❌ [ERROR] for workspace /workspace/khyretos/kk-engine Linter raw log: docker/android.Dockerfile:19 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check docker/appimage.Dockerfile:38 SC2016 info: Expressions don't expand in single quotes, use double quotes for that. docker/appimage.Dockerfile:51 DL3003 warning: Use WORKDIR to switch to a directory docker/appimage.Dockerfile:57 DL3003 warning: Use WORKDIR to switch to a directory docker/appimage.Dockerfile:63 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check docker/appimage.Dockerfile:63 DL3003 warning: Use WORKDIR to switch to a directory docker/appimage.Dockerfile:73 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check docker/appimage.Dockerfile:73 DL3003 warning: Use WORKDIR to switch to a directory docker/ci.Dockerfile:42 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check docker/ci.Dockerfile:56 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check docker/server/Dockerfile:22 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check docker/vm.Dockerfile:22 SC2086 info: Double quote to prevent globbing and word splitting. docker/vm.Dockerfile:29 DL3003 warning: Use WORKDIR to switch to a directory docker/vm.Dockerfile:29 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check website/Dockerfile:9 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check ``` </details> <details><summary>REPOSITORY · trivy: first lines of the output</summary> ```text See documentation on https://megalinter.io/9.4.0/descriptors/repository_trivy/ ----------------------------------------------- ❌ [ERROR] for workspace /workspace/khyretos/kk-engine Linter raw log: 2026-10-27T21:51:48Z INFO [vulndb] Need to update DB 2026-10-27T21:51:48Z INFO [vulndb] Downloading vulnerability DB... 2026-10-27T21:51:48Z INFO [vulndb] Downloading artifact... repo="mirror.gcr.io/aquasec/trivy-db:2" 5.96 MiB / 130.09 MiB [-->___________________________________________________________] 4.58% ? p/s ?16.00 MiB / 130.09 MiB [------->____________________________________________________] 12.30% ? p/s ?26.04 MiB / 130.09 MiB [------------>_______________________________________________] 20.02% ? p/s ?34.46 MiB / 130.09 MiB [------------>__________________________________] 26.49% 47.45 MiB p/s ETA 2s45.14 MiB / 130.09 MiB [---------------->______________________________] 34.70% 47.45 MiB p/s ETA 1s56.26 MiB / 130.09 MiB [-------------------->__________________________] 43.25% 47.45 MiB p/s ETA 1s66.00 MiB / 130.09 MiB [----------------------->_______________________] 50.74% 47.78 MiB p/s ETA 1s77.88 MiB / 130.09 MiB [---------------------------->__________________] 59.87% 47.78 MiB p/s ETA 1s87.04 MiB / 130.09 MiB [------------------------------->_______________] 66.91% 47.78 MiB p/s ETA 0s98.78 MiB / 130.09 MiB [----------------------------------->___________] 75.94% 48.20 MiB p/s ETA 0s109.48 MiB / 130.09 MiB [-------------------------------------->_______] 84.16% 48.20 MiB p/s ETA 0s116.51 MiB / 130.09 MiB [----------------------------------------->____] 89.57% 48.20 MiB p/s ETA 0s128.61 MiB / 130.09 MiB [--------------------------------------------->] 98.86% 48.30 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 48.30 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 48.30 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 45.35 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 45.35 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 45.35 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 42.42 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 42.42 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 42.42 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 39.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 39.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 39.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 37.12 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 37.12 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 37.12 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 34.73 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 34.73 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 34.73 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 32.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 32.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 32.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 30.39 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 30.39 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 30.39 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 28.43 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 28.43 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 28.43 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 26.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 26.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 26.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 24.88 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 24.88 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 24.88 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 23.28 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 23.28 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 23.28 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 21.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 21.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 21.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 20.37 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 20.37 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 20.37 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 19.06 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 19.06 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 19.06 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 17.83 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 17.83 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 17.83 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 16.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 16.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 16.68 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 15.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 15.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 15.60 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 14.59 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 14.59 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 14.59 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 13.65 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 13.65 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 13.65 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 12.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 12.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 12.77 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.95 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.95 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.95 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.18 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.18 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 11.18 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 10.46 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 10.46 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------->] 100.00% 10.46 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.78 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.78 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.78 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.15 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.15 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 9.15 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.56 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.56 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.56 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.01 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.01 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 8.01 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 7.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 7.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 7.49 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [--------------------------------------------->] 100.00% 7.01 MiB p/s ETA 0s130.09 MiB / 130.09 MiB [-------------------------------------------------] 100.00% 6.53 MiB p/s 20s2026-10-27T21:52:09Z INFO [vulndb] Artifact successfully downloaded repo="mirror.gcr.io/aquasec/trivy-db:2" 2026-10-27T21:52:09Z INFO [vuln] Vulnerability scanning is enabled 2026-10-27T21:52:09Z INFO [misconfig] Misconfiguration scanning is enabled 2026-10-27T21:52:09Z INFO [checks-client] Need to update the checks bundle 2026-10-27T21:52:09Z INFO [checks-client] Downloading the checks bundle... 234.57 KiB / 234.57 KiB [------------------------------------------------------] 100.00% ? p/s 200ms2026-10-27T21:52:12Z WARN [rego] Module will be skipped as current version of Trivy is older than minimum trivy version required - please update Trivy to use this module file_path="root/.cache/trivy/policy/content/policies/cloud/policies/aws/cloudfront/enable_logging.rego" minimum_trivy_version="0.72.0" 2026-10-27T21:52:13Z ERROR [dockerfile scanner] Failed to parse file file_path="docker/server/Dockerfile.dockerignore" err="parse dockerfile instruction: parse instruction \".git\": unknown instruction: .git" 2026-10-27T21:52:13Z INFO Number of language-specific files num=0 2026-10-27T21:52:13Z INFO Detected config files num=9 Report Summary ┌──────────────────────────────┬────────────┬─────────────────┬───────────────────┐ │ Target │ Type │ Vulnerabilities │ Misconfigurations │ ├──────────────────────────────┼────────────┼─────────────────┼───────────────────┤ │ benchmarks/docker/Dockerfile │ dockerfile │ - │ 2 │ ├──────────────────────────────┼────────────┼─────────────────┼───────────────────┤ │ docker/android.Dockerfile │ dockerfile │ - │ 2 │ ├──────────────────────────────┼────────────┼─────────────────┼───────────────────┤ │ docker/appimage.Dockerfile │ dockerfile │ - │ 5 │ … ``` </details> 🧹 Formatting only (layout, no behaviour; the nightly lint-fix job applies these as a PR): YAML · prettier (57 files checked), BASH · shfmt (11 files checked), JSON · prettier (147 files checked) ✅ Clean: actionlint, git_diff, gitleaks, grype, jsonlint, secretlint, stylelint, trufflehog, xmllint <sub>MegaLinter on soucouyant · full logs in the Actions run · comment <code>/improve</code> for AI fix suggestions</sub>
Some checks failed
CI / dependencies (pull_request) Successful in 12s
CI / std-includes (pull_request) Successful in 20s
Benchmarks / benchmarks (pull_request) Failing after 5m35s
CI / build-test-and-coverage (pull_request) Failing after 4m53s
CI / shipping-build (pull_request) Failing after 11m43s
Docs site / site (pull_request) Successful in 49s
CI / release-build (pull_request) Failing after 6m6s
lint / megalinter (pull_request) Successful in 3m11s
CI / android (pull_request) Failing after 7m57s
Windows (native) / build (pull_request) Failing after 10m8s
Windows (native) / test (pull_request) Has been skipped
Windows (native) / publish (pull_request) Has been skipped
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin +refs/pull/140/head:khyretos/claude/jiggle-breasts
git switch khyretos/claude/jiggle-breasts

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch claude/jiggle-skeleton-base
git merge --no-ff khyretos/claude/jiggle-breasts
git switch khyretos/claude/jiggle-breasts
git rebase claude/jiggle-skeleton-base
git switch claude/jiggle-skeleton-base
git merge --ff-only khyretos/claude/jiggle-breasts
git switch khyretos/claude/jiggle-breasts
git rebase claude/jiggle-skeleton-base
git switch claude/jiggle-skeleton-base
git merge --no-ff khyretos/claude/jiggle-breasts
git switch claude/jiggle-skeleton-base
git merge --squash khyretos/claude/jiggle-breasts
git switch claude/jiggle-skeleton-base
git merge --ff-only khyretos/claude/jiggle-breasts
git switch claude/jiggle-skeleton-base
git merge khyretos/claude/jiggle-breasts
git push origin claude/jiggle-skeleton-base
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
khyretos/kk-engine!140
No description provided.