Feature/stonecutter migration - #21

Merged
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration
Aug 29, 2026
Merged

Feature/stonecutter migration#21
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration

Conversation

@KP2048

Copy link
Copy Markdown
Member

No description provided.

KP2048and others added 5 commits August 28, 2026 16:06
Prerequisite for adding Stonecutter, which refuses to apply below
Gradle 9 (checked directly: 0.8.4, 0.9.1, and 0.9.7 all reject 8.x).
Verified clean on 9.7.1 first - full compile, unit tests, and the
whole task graph (Loom, Architectury, Dokka, ModFusioner, ModPublisher,
Shadow, the actualizer/archie plugins) all configure and run across
every module with no changes beyond the two below.
- Gradle 9 stopped bundling its own JUnit Platform launcher for
useJUnitPlatform() - added junit-platform-launcher to the catalog
and wired it once as testRuntimeOnly in the shared subprojects{}
dependencies block.
- core/common's verifyGuiSpriteAssets task used the `by registering {}`
delegate, deprecated in 9.6 and removed in 10 - switched to
`register("...")`.
architectury-loom's pinned version also now reads 1.17.491 instead of
1.13.469 in gradle/libs.versions.toml. This wasn't a deliberate edit -
noticed the file already showed 1.17.491 when checked, with no edit
made by this work to explain it. Left as-is since it's what actually
resolved and ran successfully throughout verification, but flagging it
since its cause is unexplained.
Converts core/{common,fabric,neoforge} to a Stonecutter-managed tree/branch
structure (settings.gradle.kts: stonecutter { create("core") { branch(...) } }),
keeping datagen/gametest/test on the old includeModule() scheme until this
slice is proven out.
Root build.gradle.kts guards subprojects{}/allprojects{} plugin application
against Stonecutter's synthetic tree/branch container projects (:core,
:core:common, etc. - real leaf projects nest under them and must not get
build plugins applied directly).
Sibling-project references (fabric/neoforge -> common) go through Stonecutter's
node.sibling("common").project API rather than a hardcoded project path -
ProjectNode.project resolves straight to the sibling's Gradle Project.
The old namedElements/transformProductionX cross-project dependency (Loom's
own common() mechanism) produces a circular task dependency under Stonecutter's
nested per-version project paths, so fabric/neoforge instead depend directly
on common's own "jar" task output as a FileCollection. (A plain SourceSetOutput
FileCollection almost works the same way, but breaks shadowJar - Shadow's copy
action expects zip-safe entries, not raw class/resource directories.)
Also bumps the Shadow plugin from com.github.johnrengelman.shadow 8.1.1 to the
maintained com.gradleup.shadow 9.6.1 fork - the old one is incompatible with
Gradle 9.7.1 (MissingPropertyException: mode in ShadowCopyAction), independent
of the Stonecutter migration itself.
Disables the background-session worktree-isolation guard for this repo
(.claude/settings.json) at the user's request.
Verified: :core:{common,fabric,neoforge}:1.21.1:assemble all succeed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
Extends the core-only Stonecutter validation slice to datagen, gametest, and
test - all four module trees are now Stonecutter-managed. settings.gradle.kts
registers all four trees identically (branch("common")/branch("fabric")/
branch("neoforge"), single version "1.21.1" each); each tree gets its own
stonecutter.gradle.kts (mirroring core's).
Sibling-project references follow the pattern established for core:
- Same-tree (X:common <-> X:fabric/neoforge): node.sibling("common").project.
- Cross-tree (e.g. datagen -> core, test -> core/datagen/gametest): Stonecutter
has no public cross-tree lookup API (node.sibling() only searches its own
tree), so these resolve via rootProject.project(":tree:branch:$version").
- Every cross-project compiled-output dependency goes through the sibling's
plain "jar" task output as a FileCollection, not project(path, configuration)
or a bare project(path) - both trigger a circular compileJava<->compileKotlin
task dependency under Stonecutter's nested per-version project paths,
confirmed live across multiple project-pairings (common<->common,
loader<->loader, common-mode<->loader). Deliberately not remapJar's output:
that transforms named->intermediary for shipping and reintroduces the same
class duplication one layer down (confirmed live: a Font/class_327
duplicate-overload regression in already-working core code, traced to a
poisoned shared .gradle/loom-cache/remapped_mods/ entry - cleared as part of
this work).
files() dependencies carry no transitive module metadata, unlike the
project(path, "namedElements") dependencies they replace, so every affected
common-mode project (datagen/gametest/test's common modules) repeats
whatever api/modApi surface its own code actually needs from its sibling
(Compose, kotlinx.serialization, storage lib) - verified by removing each
speculatively-added line and confirming the build still needs it before
keeping it (e.g. libs.rei.common was not actually needed by datagen-common).
The actualizer merges each common module's own source directly into its
fabric/neoforge siblings' compilation (not just their compiled output), so
those loader projects need common's compile-time deps directly too - same
reasoning, same fix.
gametest-neoforge needed the loader-specific libs.storage.neoforge instead of
libs.storage.common - NeoForge's remap pipeline doesn't handle
earth.terrarium.common_storage_lib's common artifact correctly (same family
of gap as the documented Cloche NeoForge remapCommon limitation for this
library); using the common variant surfaced as an ambiguous ItemResource.of
overload resolving against raw Fabric intermediary-mapped parameter types.
Verified: `./gradlew assemble` succeeds for the whole repo (all 12
common/fabric/neoforge modules across core/datagen/gametest/test).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…est/test loader modules
The files()-based cross-tree dependency on each core-{fabric,neoforge}
sibling (used to dodge the circular compileJava<->compileKotlin task
dependency documented in the previous commit) carries no runtime GAMELIBRARY
discovery either, same as it carries no compile-time transitive metadata.
core-fabric/core-neoforge each bundle the kotlinx.serialization format
add-ons (nbt/toml/json5) via bundleRuntimeLibrary - Archie's own Config
system needs all three at init - but that never propagated to any of
datagen/gametest/test's loader modules, which only had Compose repeated so
far.
Confirmed live via `./gradlew :test:fabric:1.21.1:runClient`:
Caused by: java.lang.NoClassDefFoundError: io/github/xn32/json5k/ConfigBuilder
at ...Json5ConfigSerializer.<clinit>
at ...ConfigSpec.<init>
at ...Archie.init
Same gap existed on datagen-fabric, datagen-neoforge, gametest-fabric,
gametest-neoforge, and test-neoforge (verified via each module's own
runtimeClasspath resolution, not just test-fabric where it was reported) -
fixed all six with the same runtimeLibrary(...) additions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…tonecutter
Stonecutter's nested per-version project layout broke several things that
keyed off the pre-migration flat project names:
- Maven publish's artifactId was "1.21.1" for every module (not just the
intended -fabric/-datagen-common/etc. suffix missing) - the artifactId
assignment ran before base.archivesName reached its final value. Moved it
into afterEvaluate{}. Also fixed the archie-test exclusion, which checked
project.name (now always "1.21.1") instead of project.path.
- modfusioner's fusejars task silently no-op'd ("No projects were found")
since it resolves projects by bare Project.name, and every Stonecutter tree
now has a leaf literally named "fabric"/"neoforge". Anchored it on the
unique ":core" container project and override inputFile via
gradle.projectsEvaluated once the real remapJar output paths are known.
- Dokka's per-module aggregation dependency block had been commented out
during the migration (stale flat project paths) - rebuilt against
Stonecutter's real :tree:branch:version paths.
- gameVersions in the publisher{} block now derives from
libs.versions.minecraft instead of a separately hardcoded "1.21.1" literal.
Verified: generatePomFileForMavenPublication produces correct artifactIds,
test tree is excluded, fusejars produces a real merged jar (both
fabric.mod.json and neoforge.mods.toml present), dokka configuration
resolves all 9 module paths, and publishCurseforge/publishModrinth dry-run
(debug=true) cleanly against live CurseForge/Modrinth data.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WW8YqJDBH8AFaTFirpCQGZ
@KP2048
KP2048 merged commit c35a245 into mainAug 29, 2026
1 of 2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Feature/stonecutter migration - #21

Merged
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration
Aug 29, 2026
Merged

Feature/stonecutter migration#21
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration

Conversation

@KP2048

Copy link
Copy Markdown
Member

No description provided.

KP2048and others added 5 commits August 28, 2026 16:06
Prerequisite for adding Stonecutter, which refuses to apply below
Gradle 9 (checked directly: 0.8.4, 0.9.1, and 0.9.7 all reject 8.x).
Verified clean on 9.7.1 first - full compile, unit tests, and the
whole task graph (Loom, Architectury, Dokka, ModFusioner, ModPublisher,
Shadow, the actualizer/archie plugins) all configure and run across
every module with no changes beyond the two below.
- Gradle 9 stopped bundling its own JUnit Platform launcher for
useJUnitPlatform() - added junit-platform-launcher to the catalog
and wired it once as testRuntimeOnly in the shared subprojects{}
dependencies block.
- core/common's verifyGuiSpriteAssets task used the `by registering {}`
delegate, deprecated in 9.6 and removed in 10 - switched to
`register("...")`.
architectury-loom's pinned version also now reads 1.17.491 instead of
1.13.469 in gradle/libs.versions.toml. This wasn't a deliberate edit -
noticed the file already showed 1.17.491 when checked, with no edit
made by this work to explain it. Left as-is since it's what actually
resolved and ran successfully throughout verification, but flagging it
since its cause is unexplained.
Converts core/{common,fabric,neoforge} to a Stonecutter-managed tree/branch
structure (settings.gradle.kts: stonecutter { create("core") { branch(...) } }),
keeping datagen/gametest/test on the old includeModule() scheme until this
slice is proven out.
Root build.gradle.kts guards subprojects{}/allprojects{} plugin application
against Stonecutter's synthetic tree/branch container projects (:core,
:core:common, etc. - real leaf projects nest under them and must not get
build plugins applied directly).
Sibling-project references (fabric/neoforge -> common) go through Stonecutter's
node.sibling("common").project API rather than a hardcoded project path -
ProjectNode.project resolves straight to the sibling's Gradle Project.
The old namedElements/transformProductionX cross-project dependency (Loom's
own common() mechanism) produces a circular task dependency under Stonecutter's
nested per-version project paths, so fabric/neoforge instead depend directly
on common's own "jar" task output as a FileCollection. (A plain SourceSetOutput
FileCollection almost works the same way, but breaks shadowJar - Shadow's copy
action expects zip-safe entries, not raw class/resource directories.)
Also bumps the Shadow plugin from com.github.johnrengelman.shadow 8.1.1 to the
maintained com.gradleup.shadow 9.6.1 fork - the old one is incompatible with
Gradle 9.7.1 (MissingPropertyException: mode in ShadowCopyAction), independent
of the Stonecutter migration itself.
Disables the background-session worktree-isolation guard for this repo
(.claude/settings.json) at the user's request.
Verified: :core:{common,fabric,neoforge}:1.21.1:assemble all succeed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
Extends the core-only Stonecutter validation slice to datagen, gametest, and
test - all four module trees are now Stonecutter-managed. settings.gradle.kts
registers all four trees identically (branch("common")/branch("fabric")/
branch("neoforge"), single version "1.21.1" each); each tree gets its own
stonecutter.gradle.kts (mirroring core's).
Sibling-project references follow the pattern established for core:
- Same-tree (X:common <-> X:fabric/neoforge): node.sibling("common").project.
- Cross-tree (e.g. datagen -> core, test -> core/datagen/gametest): Stonecutter
has no public cross-tree lookup API (node.sibling() only searches its own
tree), so these resolve via rootProject.project(":tree:branch:$version").
- Every cross-project compiled-output dependency goes through the sibling's
plain "jar" task output as a FileCollection, not project(path, configuration)
or a bare project(path) - both trigger a circular compileJava<->compileKotlin
task dependency under Stonecutter's nested per-version project paths,
confirmed live across multiple project-pairings (common<->common,
loader<->loader, common-mode<->loader). Deliberately not remapJar's output:
that transforms named->intermediary for shipping and reintroduces the same
class duplication one layer down (confirmed live: a Font/class_327
duplicate-overload regression in already-working core code, traced to a
poisoned shared .gradle/loom-cache/remapped_mods/ entry - cleared as part of
this work).
files() dependencies carry no transitive module metadata, unlike the
project(path, "namedElements") dependencies they replace, so every affected
common-mode project (datagen/gametest/test's common modules) repeats
whatever api/modApi surface its own code actually needs from its sibling
(Compose, kotlinx.serialization, storage lib) - verified by removing each
speculatively-added line and confirming the build still needs it before
keeping it (e.g. libs.rei.common was not actually needed by datagen-common).
The actualizer merges each common module's own source directly into its
fabric/neoforge siblings' compilation (not just their compiled output), so
those loader projects need common's compile-time deps directly too - same
reasoning, same fix.
gametest-neoforge needed the loader-specific libs.storage.neoforge instead of
libs.storage.common - NeoForge's remap pipeline doesn't handle
earth.terrarium.common_storage_lib's common artifact correctly (same family
of gap as the documented Cloche NeoForge remapCommon limitation for this
library); using the common variant surfaced as an ambiguous ItemResource.of
overload resolving against raw Fabric intermediary-mapped parameter types.
Verified: `./gradlew assemble` succeeds for the whole repo (all 12
common/fabric/neoforge modules across core/datagen/gametest/test).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…est/test loader modules
The files()-based cross-tree dependency on each core-{fabric,neoforge}
sibling (used to dodge the circular compileJava<->compileKotlin task
dependency documented in the previous commit) carries no runtime GAMELIBRARY
discovery either, same as it carries no compile-time transitive metadata.
core-fabric/core-neoforge each bundle the kotlinx.serialization format
add-ons (nbt/toml/json5) via bundleRuntimeLibrary - Archie's own Config
system needs all three at init - but that never propagated to any of
datagen/gametest/test's loader modules, which only had Compose repeated so
far.
Confirmed live via `./gradlew :test:fabric:1.21.1:runClient`:
Caused by: java.lang.NoClassDefFoundError: io/github/xn32/json5k/ConfigBuilder
at ...Json5ConfigSerializer.<clinit>
at ...ConfigSpec.<init>
at ...Archie.init
Same gap existed on datagen-fabric, datagen-neoforge, gametest-fabric,
gametest-neoforge, and test-neoforge (verified via each module's own
runtimeClasspath resolution, not just test-fabric where it was reported) -
fixed all six with the same runtimeLibrary(...) additions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…tonecutter
Stonecutter's nested per-version project layout broke several things that
keyed off the pre-migration flat project names:
- Maven publish's artifactId was "1.21.1" for every module (not just the
intended -fabric/-datagen-common/etc. suffix missing) - the artifactId
assignment ran before base.archivesName reached its final value. Moved it
into afterEvaluate{}. Also fixed the archie-test exclusion, which checked
project.name (now always "1.21.1") instead of project.path.
- modfusioner's fusejars task silently no-op'd ("No projects were found")
since it resolves projects by bare Project.name, and every Stonecutter tree
now has a leaf literally named "fabric"/"neoforge". Anchored it on the
unique ":core" container project and override inputFile via
gradle.projectsEvaluated once the real remapJar output paths are known.
- Dokka's per-module aggregation dependency block had been commented out
during the migration (stale flat project paths) - rebuilt against
Stonecutter's real :tree:branch:version paths.
- gameVersions in the publisher{} block now derives from
libs.versions.minecraft instead of a separately hardcoded "1.21.1" literal.
Verified: generatePomFileForMavenPublication produces correct artifactIds,
test tree is excluded, fusejars produces a real merged jar (both
fabric.mod.json and neoforge.mods.toml present), dokka configuration
resolves all 9 module paths, and publishCurseforge/publishModrinth dry-run
(debug=true) cleanly against live CurseForge/Modrinth data.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WW8YqJDBH8AFaTFirpCQGZ
@KP2048
KP2048 merged commit c35a245 into mainAug 29, 2026
1 of 2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Feature/stonecutter migration - #21

Merged
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration
Aug 29, 2026
Merged

Feature/stonecutter migration#21
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration

Conversation

@KP2048

Copy link
Copy Markdown
Member

No description provided.

KP2048and others added 5 commits August 28, 2026 16:06
Prerequisite for adding Stonecutter, which refuses to apply below
Gradle 9 (checked directly: 0.8.4, 0.9.1, and 0.9.7 all reject 8.x).
Verified clean on 9.7.1 first - full compile, unit tests, and the
whole task graph (Loom, Architectury, Dokka, ModFusioner, ModPublisher,
Shadow, the actualizer/archie plugins) all configure and run across
every module with no changes beyond the two below.
- Gradle 9 stopped bundling its own JUnit Platform launcher for
useJUnitPlatform() - added junit-platform-launcher to the catalog
and wired it once as testRuntimeOnly in the shared subprojects{}
dependencies block.
- core/common's verifyGuiSpriteAssets task used the `by registering {}`
delegate, deprecated in 9.6 and removed in 10 - switched to
`register("...")`.
architectury-loom's pinned version also now reads 1.17.491 instead of
1.13.469 in gradle/libs.versions.toml. This wasn't a deliberate edit -
noticed the file already showed 1.17.491 when checked, with no edit
made by this work to explain it. Left as-is since it's what actually
resolved and ran successfully throughout verification, but flagging it
since its cause is unexplained.
Converts core/{common,fabric,neoforge} to a Stonecutter-managed tree/branch
structure (settings.gradle.kts: stonecutter { create("core") { branch(...) } }),
keeping datagen/gametest/test on the old includeModule() scheme until this
slice is proven out.
Root build.gradle.kts guards subprojects{}/allprojects{} plugin application
against Stonecutter's synthetic tree/branch container projects (:core,
:core:common, etc. - real leaf projects nest under them and must not get
build plugins applied directly).
Sibling-project references (fabric/neoforge -> common) go through Stonecutter's
node.sibling("common").project API rather than a hardcoded project path -
ProjectNode.project resolves straight to the sibling's Gradle Project.
The old namedElements/transformProductionX cross-project dependency (Loom's
own common() mechanism) produces a circular task dependency under Stonecutter's
nested per-version project paths, so fabric/neoforge instead depend directly
on common's own "jar" task output as a FileCollection. (A plain SourceSetOutput
FileCollection almost works the same way, but breaks shadowJar - Shadow's copy
action expects zip-safe entries, not raw class/resource directories.)
Also bumps the Shadow plugin from com.github.johnrengelman.shadow 8.1.1 to the
maintained com.gradleup.shadow 9.6.1 fork - the old one is incompatible with
Gradle 9.7.1 (MissingPropertyException: mode in ShadowCopyAction), independent
of the Stonecutter migration itself.
Disables the background-session worktree-isolation guard for this repo
(.claude/settings.json) at the user's request.
Verified: :core:{common,fabric,neoforge}:1.21.1:assemble all succeed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
Extends the core-only Stonecutter validation slice to datagen, gametest, and
test - all four module trees are now Stonecutter-managed. settings.gradle.kts
registers all four trees identically (branch("common")/branch("fabric")/
branch("neoforge"), single version "1.21.1" each); each tree gets its own
stonecutter.gradle.kts (mirroring core's).
Sibling-project references follow the pattern established for core:
- Same-tree (X:common <-> X:fabric/neoforge): node.sibling("common").project.
- Cross-tree (e.g. datagen -> core, test -> core/datagen/gametest): Stonecutter
has no public cross-tree lookup API (node.sibling() only searches its own
tree), so these resolve via rootProject.project(":tree:branch:$version").
- Every cross-project compiled-output dependency goes through the sibling's
plain "jar" task output as a FileCollection, not project(path, configuration)
or a bare project(path) - both trigger a circular compileJava<->compileKotlin
task dependency under Stonecutter's nested per-version project paths,
confirmed live across multiple project-pairings (common<->common,
loader<->loader, common-mode<->loader). Deliberately not remapJar's output:
that transforms named->intermediary for shipping and reintroduces the same
class duplication one layer down (confirmed live: a Font/class_327
duplicate-overload regression in already-working core code, traced to a
poisoned shared .gradle/loom-cache/remapped_mods/ entry - cleared as part of
this work).
files() dependencies carry no transitive module metadata, unlike the
project(path, "namedElements") dependencies they replace, so every affected
common-mode project (datagen/gametest/test's common modules) repeats
whatever api/modApi surface its own code actually needs from its sibling
(Compose, kotlinx.serialization, storage lib) - verified by removing each
speculatively-added line and confirming the build still needs it before
keeping it (e.g. libs.rei.common was not actually needed by datagen-common).
The actualizer merges each common module's own source directly into its
fabric/neoforge siblings' compilation (not just their compiled output), so
those loader projects need common's compile-time deps directly too - same
reasoning, same fix.
gametest-neoforge needed the loader-specific libs.storage.neoforge instead of
libs.storage.common - NeoForge's remap pipeline doesn't handle
earth.terrarium.common_storage_lib's common artifact correctly (same family
of gap as the documented Cloche NeoForge remapCommon limitation for this
library); using the common variant surfaced as an ambiguous ItemResource.of
overload resolving against raw Fabric intermediary-mapped parameter types.
Verified: `./gradlew assemble` succeeds for the whole repo (all 12
common/fabric/neoforge modules across core/datagen/gametest/test).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…est/test loader modules
The files()-based cross-tree dependency on each core-{fabric,neoforge}
sibling (used to dodge the circular compileJava<->compileKotlin task
dependency documented in the previous commit) carries no runtime GAMELIBRARY
discovery either, same as it carries no compile-time transitive metadata.
core-fabric/core-neoforge each bundle the kotlinx.serialization format
add-ons (nbt/toml/json5) via bundleRuntimeLibrary - Archie's own Config
system needs all three at init - but that never propagated to any of
datagen/gametest/test's loader modules, which only had Compose repeated so
far.
Confirmed live via `./gradlew :test:fabric:1.21.1:runClient`:
Caused by: java.lang.NoClassDefFoundError: io/github/xn32/json5k/ConfigBuilder
at ...Json5ConfigSerializer.<clinit>
at ...ConfigSpec.<init>
at ...Archie.init
Same gap existed on datagen-fabric, datagen-neoforge, gametest-fabric,
gametest-neoforge, and test-neoforge (verified via each module's own
runtimeClasspath resolution, not just test-fabric where it was reported) -
fixed all six with the same runtimeLibrary(...) additions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…tonecutter
Stonecutter's nested per-version project layout broke several things that
keyed off the pre-migration flat project names:
- Maven publish's artifactId was "1.21.1" for every module (not just the
intended -fabric/-datagen-common/etc. suffix missing) - the artifactId
assignment ran before base.archivesName reached its final value. Moved it
into afterEvaluate{}. Also fixed the archie-test exclusion, which checked
project.name (now always "1.21.1") instead of project.path.
- modfusioner's fusejars task silently no-op'd ("No projects were found")
since it resolves projects by bare Project.name, and every Stonecutter tree
now has a leaf literally named "fabric"/"neoforge". Anchored it on the
unique ":core" container project and override inputFile via
gradle.projectsEvaluated once the real remapJar output paths are known.
- Dokka's per-module aggregation dependency block had been commented out
during the migration (stale flat project paths) - rebuilt against
Stonecutter's real :tree:branch:version paths.
- gameVersions in the publisher{} block now derives from
libs.versions.minecraft instead of a separately hardcoded "1.21.1" literal.
Verified: generatePomFileForMavenPublication produces correct artifactIds,
test tree is excluded, fusejars produces a real merged jar (both
fabric.mod.json and neoforge.mods.toml present), dokka configuration
resolves all 9 module paths, and publishCurseforge/publishModrinth dry-run
(debug=true) cleanly against live CurseForge/Modrinth data.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WW8YqJDBH8AFaTFirpCQGZ
@KP2048
KP2048 merged commit c35a245 into mainAug 29, 2026
1 of 2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Feature/stonecutter migration - #21

Merged
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration
Aug 29, 2026
Merged

Feature/stonecutter migration#21
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration

Conversation

@KP2048

Copy link
Copy Markdown
Member

No description provided.

KP2048and others added 5 commits August 28, 2026 16:06
Prerequisite for adding Stonecutter, which refuses to apply below
Gradle 9 (checked directly: 0.8.4, 0.9.1, and 0.9.7 all reject 8.x).
Verified clean on 9.7.1 first - full compile, unit tests, and the
whole task graph (Loom, Architectury, Dokka, ModFusioner, ModPublisher,
Shadow, the actualizer/archie plugins) all configure and run across
every module with no changes beyond the two below.
- Gradle 9 stopped bundling its own JUnit Platform launcher for
useJUnitPlatform() - added junit-platform-launcher to the catalog
and wired it once as testRuntimeOnly in the shared subprojects{}
dependencies block.
- core/common's verifyGuiSpriteAssets task used the `by registering {}`
delegate, deprecated in 9.6 and removed in 10 - switched to
`register("...")`.
architectury-loom's pinned version also now reads 1.17.491 instead of
1.13.469 in gradle/libs.versions.toml. This wasn't a deliberate edit -
noticed the file already showed 1.17.491 when checked, with no edit
made by this work to explain it. Left as-is since it's what actually
resolved and ran successfully throughout verification, but flagging it
since its cause is unexplained.
Converts core/{common,fabric,neoforge} to a Stonecutter-managed tree/branch
structure (settings.gradle.kts: stonecutter { create("core") { branch(...) } }),
keeping datagen/gametest/test on the old includeModule() scheme until this
slice is proven out.
Root build.gradle.kts guards subprojects{}/allprojects{} plugin application
against Stonecutter's synthetic tree/branch container projects (:core,
:core:common, etc. - real leaf projects nest under them and must not get
build plugins applied directly).
Sibling-project references (fabric/neoforge -> common) go through Stonecutter's
node.sibling("common").project API rather than a hardcoded project path -
ProjectNode.project resolves straight to the sibling's Gradle Project.
The old namedElements/transformProductionX cross-project dependency (Loom's
own common() mechanism) produces a circular task dependency under Stonecutter's
nested per-version project paths, so fabric/neoforge instead depend directly
on common's own "jar" task output as a FileCollection. (A plain SourceSetOutput
FileCollection almost works the same way, but breaks shadowJar - Shadow's copy
action expects zip-safe entries, not raw class/resource directories.)
Also bumps the Shadow plugin from com.github.johnrengelman.shadow 8.1.1 to the
maintained com.gradleup.shadow 9.6.1 fork - the old one is incompatible with
Gradle 9.7.1 (MissingPropertyException: mode in ShadowCopyAction), independent
of the Stonecutter migration itself.
Disables the background-session worktree-isolation guard for this repo
(.claude/settings.json) at the user's request.
Verified: :core:{common,fabric,neoforge}:1.21.1:assemble all succeed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
Extends the core-only Stonecutter validation slice to datagen, gametest, and
test - all four module trees are now Stonecutter-managed. settings.gradle.kts
registers all four trees identically (branch("common")/branch("fabric")/
branch("neoforge"), single version "1.21.1" each); each tree gets its own
stonecutter.gradle.kts (mirroring core's).
Sibling-project references follow the pattern established for core:
- Same-tree (X:common <-> X:fabric/neoforge): node.sibling("common").project.
- Cross-tree (e.g. datagen -> core, test -> core/datagen/gametest): Stonecutter
has no public cross-tree lookup API (node.sibling() only searches its own
tree), so these resolve via rootProject.project(":tree:branch:$version").
- Every cross-project compiled-output dependency goes through the sibling's
plain "jar" task output as a FileCollection, not project(path, configuration)
or a bare project(path) - both trigger a circular compileJava<->compileKotlin
task dependency under Stonecutter's nested per-version project paths,
confirmed live across multiple project-pairings (common<->common,
loader<->loader, common-mode<->loader). Deliberately not remapJar's output:
that transforms named->intermediary for shipping and reintroduces the same
class duplication one layer down (confirmed live: a Font/class_327
duplicate-overload regression in already-working core code, traced to a
poisoned shared .gradle/loom-cache/remapped_mods/ entry - cleared as part of
this work).
files() dependencies carry no transitive module metadata, unlike the
project(path, "namedElements") dependencies they replace, so every affected
common-mode project (datagen/gametest/test's common modules) repeats
whatever api/modApi surface its own code actually needs from its sibling
(Compose, kotlinx.serialization, storage lib) - verified by removing each
speculatively-added line and confirming the build still needs it before
keeping it (e.g. libs.rei.common was not actually needed by datagen-common).
The actualizer merges each common module's own source directly into its
fabric/neoforge siblings' compilation (not just their compiled output), so
those loader projects need common's compile-time deps directly too - same
reasoning, same fix.
gametest-neoforge needed the loader-specific libs.storage.neoforge instead of
libs.storage.common - NeoForge's remap pipeline doesn't handle
earth.terrarium.common_storage_lib's common artifact correctly (same family
of gap as the documented Cloche NeoForge remapCommon limitation for this
library); using the common variant surfaced as an ambiguous ItemResource.of
overload resolving against raw Fabric intermediary-mapped parameter types.
Verified: `./gradlew assemble` succeeds for the whole repo (all 12
common/fabric/neoforge modules across core/datagen/gametest/test).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…est/test loader modules
The files()-based cross-tree dependency on each core-{fabric,neoforge}
sibling (used to dodge the circular compileJava<->compileKotlin task
dependency documented in the previous commit) carries no runtime GAMELIBRARY
discovery either, same as it carries no compile-time transitive metadata.
core-fabric/core-neoforge each bundle the kotlinx.serialization format
add-ons (nbt/toml/json5) via bundleRuntimeLibrary - Archie's own Config
system needs all three at init - but that never propagated to any of
datagen/gametest/test's loader modules, which only had Compose repeated so
far.
Confirmed live via `./gradlew :test:fabric:1.21.1:runClient`:
Caused by: java.lang.NoClassDefFoundError: io/github/xn32/json5k/ConfigBuilder
at ...Json5ConfigSerializer.<clinit>
at ...ConfigSpec.<init>
at ...Archie.init
Same gap existed on datagen-fabric, datagen-neoforge, gametest-fabric,
gametest-neoforge, and test-neoforge (verified via each module's own
runtimeClasspath resolution, not just test-fabric where it was reported) -
fixed all six with the same runtimeLibrary(...) additions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…tonecutter
Stonecutter's nested per-version project layout broke several things that
keyed off the pre-migration flat project names:
- Maven publish's artifactId was "1.21.1" for every module (not just the
intended -fabric/-datagen-common/etc. suffix missing) - the artifactId
assignment ran before base.archivesName reached its final value. Moved it
into afterEvaluate{}. Also fixed the archie-test exclusion, which checked
project.name (now always "1.21.1") instead of project.path.
- modfusioner's fusejars task silently no-op'd ("No projects were found")
since it resolves projects by bare Project.name, and every Stonecutter tree
now has a leaf literally named "fabric"/"neoforge". Anchored it on the
unique ":core" container project and override inputFile via
gradle.projectsEvaluated once the real remapJar output paths are known.
- Dokka's per-module aggregation dependency block had been commented out
during the migration (stale flat project paths) - rebuilt against
Stonecutter's real :tree:branch:version paths.
- gameVersions in the publisher{} block now derives from
libs.versions.minecraft instead of a separately hardcoded "1.21.1" literal.
Verified: generatePomFileForMavenPublication produces correct artifactIds,
test tree is excluded, fusejars produces a real merged jar (both
fabric.mod.json and neoforge.mods.toml present), dokka configuration
resolves all 9 module paths, and publishCurseforge/publishModrinth dry-run
(debug=true) cleanly against live CurseForge/Modrinth data.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WW8YqJDBH8AFaTFirpCQGZ
@KP2048
KP2048 merged commit c35a245 into mainAug 29, 2026
1 of 2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Feature/stonecutter migration - #21

Merged
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration
Aug 29, 2026
Merged

Feature/stonecutter migration#21
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration

Conversation

@KP2048

Copy link
Copy Markdown
Member

No description provided.

KP2048and others added 5 commits August 28, 2026 16:06
Prerequisite for adding Stonecutter, which refuses to apply below
Gradle 9 (checked directly: 0.8.4, 0.9.1, and 0.9.7 all reject 8.x).
Verified clean on 9.7.1 first - full compile, unit tests, and the
whole task graph (Loom, Architectury, Dokka, ModFusioner, ModPublisher,
Shadow, the actualizer/archie plugins) all configure and run across
every module with no changes beyond the two below.
- Gradle 9 stopped bundling its own JUnit Platform launcher for
useJUnitPlatform() - added junit-platform-launcher to the catalog
and wired it once as testRuntimeOnly in the shared subprojects{}
dependencies block.
- core/common's verifyGuiSpriteAssets task used the `by registering {}`
delegate, deprecated in 9.6 and removed in 10 - switched to
`register("...")`.
architectury-loom's pinned version also now reads 1.17.491 instead of
1.13.469 in gradle/libs.versions.toml. This wasn't a deliberate edit -
noticed the file already showed 1.17.491 when checked, with no edit
made by this work to explain it. Left as-is since it's what actually
resolved and ran successfully throughout verification, but flagging it
since its cause is unexplained.
Converts core/{common,fabric,neoforge} to a Stonecutter-managed tree/branch
structure (settings.gradle.kts: stonecutter { create("core") { branch(...) } }),
keeping datagen/gametest/test on the old includeModule() scheme until this
slice is proven out.
Root build.gradle.kts guards subprojects{}/allprojects{} plugin application
against Stonecutter's synthetic tree/branch container projects (:core,
:core:common, etc. - real leaf projects nest under them and must not get
build plugins applied directly).
Sibling-project references (fabric/neoforge -> common) go through Stonecutter's
node.sibling("common").project API rather than a hardcoded project path -
ProjectNode.project resolves straight to the sibling's Gradle Project.
The old namedElements/transformProductionX cross-project dependency (Loom's
own common() mechanism) produces a circular task dependency under Stonecutter's
nested per-version project paths, so fabric/neoforge instead depend directly
on common's own "jar" task output as a FileCollection. (A plain SourceSetOutput
FileCollection almost works the same way, but breaks shadowJar - Shadow's copy
action expects zip-safe entries, not raw class/resource directories.)
Also bumps the Shadow plugin from com.github.johnrengelman.shadow 8.1.1 to the
maintained com.gradleup.shadow 9.6.1 fork - the old one is incompatible with
Gradle 9.7.1 (MissingPropertyException: mode in ShadowCopyAction), independent
of the Stonecutter migration itself.
Disables the background-session worktree-isolation guard for this repo
(.claude/settings.json) at the user's request.
Verified: :core:{common,fabric,neoforge}:1.21.1:assemble all succeed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
Extends the core-only Stonecutter validation slice to datagen, gametest, and
test - all four module trees are now Stonecutter-managed. settings.gradle.kts
registers all four trees identically (branch("common")/branch("fabric")/
branch("neoforge"), single version "1.21.1" each); each tree gets its own
stonecutter.gradle.kts (mirroring core's).
Sibling-project references follow the pattern established for core:
- Same-tree (X:common <-> X:fabric/neoforge): node.sibling("common").project.
- Cross-tree (e.g. datagen -> core, test -> core/datagen/gametest): Stonecutter
has no public cross-tree lookup API (node.sibling() only searches its own
tree), so these resolve via rootProject.project(":tree:branch:$version").
- Every cross-project compiled-output dependency goes through the sibling's
plain "jar" task output as a FileCollection, not project(path, configuration)
or a bare project(path) - both trigger a circular compileJava<->compileKotlin
task dependency under Stonecutter's nested per-version project paths,
confirmed live across multiple project-pairings (common<->common,
loader<->loader, common-mode<->loader). Deliberately not remapJar's output:
that transforms named->intermediary for shipping and reintroduces the same
class duplication one layer down (confirmed live: a Font/class_327
duplicate-overload regression in already-working core code, traced to a
poisoned shared .gradle/loom-cache/remapped_mods/ entry - cleared as part of
this work).
files() dependencies carry no transitive module metadata, unlike the
project(path, "namedElements") dependencies they replace, so every affected
common-mode project (datagen/gametest/test's common modules) repeats
whatever api/modApi surface its own code actually needs from its sibling
(Compose, kotlinx.serialization, storage lib) - verified by removing each
speculatively-added line and confirming the build still needs it before
keeping it (e.g. libs.rei.common was not actually needed by datagen-common).
The actualizer merges each common module's own source directly into its
fabric/neoforge siblings' compilation (not just their compiled output), so
those loader projects need common's compile-time deps directly too - same
reasoning, same fix.
gametest-neoforge needed the loader-specific libs.storage.neoforge instead of
libs.storage.common - NeoForge's remap pipeline doesn't handle
earth.terrarium.common_storage_lib's common artifact correctly (same family
of gap as the documented Cloche NeoForge remapCommon limitation for this
library); using the common variant surfaced as an ambiguous ItemResource.of
overload resolving against raw Fabric intermediary-mapped parameter types.
Verified: `./gradlew assemble` succeeds for the whole repo (all 12
common/fabric/neoforge modules across core/datagen/gametest/test).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…est/test loader modules
The files()-based cross-tree dependency on each core-{fabric,neoforge}
sibling (used to dodge the circular compileJava<->compileKotlin task
dependency documented in the previous commit) carries no runtime GAMELIBRARY
discovery either, same as it carries no compile-time transitive metadata.
core-fabric/core-neoforge each bundle the kotlinx.serialization format
add-ons (nbt/toml/json5) via bundleRuntimeLibrary - Archie's own Config
system needs all three at init - but that never propagated to any of
datagen/gametest/test's loader modules, which only had Compose repeated so
far.
Confirmed live via `./gradlew :test:fabric:1.21.1:runClient`:
Caused by: java.lang.NoClassDefFoundError: io/github/xn32/json5k/ConfigBuilder
at ...Json5ConfigSerializer.<clinit>
at ...ConfigSpec.<init>
at ...Archie.init
Same gap existed on datagen-fabric, datagen-neoforge, gametest-fabric,
gametest-neoforge, and test-neoforge (verified via each module's own
runtimeClasspath resolution, not just test-fabric where it was reported) -
fixed all six with the same runtimeLibrary(...) additions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…tonecutter
Stonecutter's nested per-version project layout broke several things that
keyed off the pre-migration flat project names:
- Maven publish's artifactId was "1.21.1" for every module (not just the
intended -fabric/-datagen-common/etc. suffix missing) - the artifactId
assignment ran before base.archivesName reached its final value. Moved it
into afterEvaluate{}. Also fixed the archie-test exclusion, which checked
project.name (now always "1.21.1") instead of project.path.
- modfusioner's fusejars task silently no-op'd ("No projects were found")
since it resolves projects by bare Project.name, and every Stonecutter tree
now has a leaf literally named "fabric"/"neoforge". Anchored it on the
unique ":core" container project and override inputFile via
gradle.projectsEvaluated once the real remapJar output paths are known.
- Dokka's per-module aggregation dependency block had been commented out
during the migration (stale flat project paths) - rebuilt against
Stonecutter's real :tree:branch:version paths.
- gameVersions in the publisher{} block now derives from
libs.versions.minecraft instead of a separately hardcoded "1.21.1" literal.
Verified: generatePomFileForMavenPublication produces correct artifactIds,
test tree is excluded, fusejars produces a real merged jar (both
fabric.mod.json and neoforge.mods.toml present), dokka configuration
resolves all 9 module paths, and publishCurseforge/publishModrinth dry-run
(debug=true) cleanly against live CurseForge/Modrinth data.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WW8YqJDBH8AFaTFirpCQGZ
@KP2048
KP2048 merged commit c35a245 into mainAug 29, 2026
1 of 2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Feature/stonecutter migration - #21

Merged
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration
Aug 29, 2026
Merged

Feature/stonecutter migration#21
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration

Conversation

@KP2048

Copy link
Copy Markdown
Member

No description provided.

KP2048and others added 5 commits August 28, 2026 16:06
Prerequisite for adding Stonecutter, which refuses to apply below
Gradle 9 (checked directly: 0.8.4, 0.9.1, and 0.9.7 all reject 8.x).
Verified clean on 9.7.1 first - full compile, unit tests, and the
whole task graph (Loom, Architectury, Dokka, ModFusioner, ModPublisher,
Shadow, the actualizer/archie plugins) all configure and run across
every module with no changes beyond the two below.
- Gradle 9 stopped bundling its own JUnit Platform launcher for
useJUnitPlatform() - added junit-platform-launcher to the catalog
and wired it once as testRuntimeOnly in the shared subprojects{}
dependencies block.
- core/common's verifyGuiSpriteAssets task used the `by registering {}`
delegate, deprecated in 9.6 and removed in 10 - switched to
`register("...")`.
architectury-loom's pinned version also now reads 1.17.491 instead of
1.13.469 in gradle/libs.versions.toml. This wasn't a deliberate edit -
noticed the file already showed 1.17.491 when checked, with no edit
made by this work to explain it. Left as-is since it's what actually
resolved and ran successfully throughout verification, but flagging it
since its cause is unexplained.
Converts core/{common,fabric,neoforge} to a Stonecutter-managed tree/branch
structure (settings.gradle.kts: stonecutter { create("core") { branch(...) } }),
keeping datagen/gametest/test on the old includeModule() scheme until this
slice is proven out.
Root build.gradle.kts guards subprojects{}/allprojects{} plugin application
against Stonecutter's synthetic tree/branch container projects (:core,
:core:common, etc. - real leaf projects nest under them and must not get
build plugins applied directly).
Sibling-project references (fabric/neoforge -> common) go through Stonecutter's
node.sibling("common").project API rather than a hardcoded project path -
ProjectNode.project resolves straight to the sibling's Gradle Project.
The old namedElements/transformProductionX cross-project dependency (Loom's
own common() mechanism) produces a circular task dependency under Stonecutter's
nested per-version project paths, so fabric/neoforge instead depend directly
on common's own "jar" task output as a FileCollection. (A plain SourceSetOutput
FileCollection almost works the same way, but breaks shadowJar - Shadow's copy
action expects zip-safe entries, not raw class/resource directories.)
Also bumps the Shadow plugin from com.github.johnrengelman.shadow 8.1.1 to the
maintained com.gradleup.shadow 9.6.1 fork - the old one is incompatible with
Gradle 9.7.1 (MissingPropertyException: mode in ShadowCopyAction), independent
of the Stonecutter migration itself.
Disables the background-session worktree-isolation guard for this repo
(.claude/settings.json) at the user's request.
Verified: :core:{common,fabric,neoforge}:1.21.1:assemble all succeed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
Extends the core-only Stonecutter validation slice to datagen, gametest, and
test - all four module trees are now Stonecutter-managed. settings.gradle.kts
registers all four trees identically (branch("common")/branch("fabric")/
branch("neoforge"), single version "1.21.1" each); each tree gets its own
stonecutter.gradle.kts (mirroring core's).
Sibling-project references follow the pattern established for core:
- Same-tree (X:common <-> X:fabric/neoforge): node.sibling("common").project.
- Cross-tree (e.g. datagen -> core, test -> core/datagen/gametest): Stonecutter
has no public cross-tree lookup API (node.sibling() only searches its own
tree), so these resolve via rootProject.project(":tree:branch:$version").
- Every cross-project compiled-output dependency goes through the sibling's
plain "jar" task output as a FileCollection, not project(path, configuration)
or a bare project(path) - both trigger a circular compileJava<->compileKotlin
task dependency under Stonecutter's nested per-version project paths,
confirmed live across multiple project-pairings (common<->common,
loader<->loader, common-mode<->loader). Deliberately not remapJar's output:
that transforms named->intermediary for shipping and reintroduces the same
class duplication one layer down (confirmed live: a Font/class_327
duplicate-overload regression in already-working core code, traced to a
poisoned shared .gradle/loom-cache/remapped_mods/ entry - cleared as part of
this work).
files() dependencies carry no transitive module metadata, unlike the
project(path, "namedElements") dependencies they replace, so every affected
common-mode project (datagen/gametest/test's common modules) repeats
whatever api/modApi surface its own code actually needs from its sibling
(Compose, kotlinx.serialization, storage lib) - verified by removing each
speculatively-added line and confirming the build still needs it before
keeping it (e.g. libs.rei.common was not actually needed by datagen-common).
The actualizer merges each common module's own source directly into its
fabric/neoforge siblings' compilation (not just their compiled output), so
those loader projects need common's compile-time deps directly too - same
reasoning, same fix.
gametest-neoforge needed the loader-specific libs.storage.neoforge instead of
libs.storage.common - NeoForge's remap pipeline doesn't handle
earth.terrarium.common_storage_lib's common artifact correctly (same family
of gap as the documented Cloche NeoForge remapCommon limitation for this
library); using the common variant surfaced as an ambiguous ItemResource.of
overload resolving against raw Fabric intermediary-mapped parameter types.
Verified: `./gradlew assemble` succeeds for the whole repo (all 12
common/fabric/neoforge modules across core/datagen/gametest/test).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…est/test loader modules
The files()-based cross-tree dependency on each core-{fabric,neoforge}
sibling (used to dodge the circular compileJava<->compileKotlin task
dependency documented in the previous commit) carries no runtime GAMELIBRARY
discovery either, same as it carries no compile-time transitive metadata.
core-fabric/core-neoforge each bundle the kotlinx.serialization format
add-ons (nbt/toml/json5) via bundleRuntimeLibrary - Archie's own Config
system needs all three at init - but that never propagated to any of
datagen/gametest/test's loader modules, which only had Compose repeated so
far.
Confirmed live via `./gradlew :test:fabric:1.21.1:runClient`:
Caused by: java.lang.NoClassDefFoundError: io/github/xn32/json5k/ConfigBuilder
at ...Json5ConfigSerializer.<clinit>
at ...ConfigSpec.<init>
at ...Archie.init
Same gap existed on datagen-fabric, datagen-neoforge, gametest-fabric,
gametest-neoforge, and test-neoforge (verified via each module's own
runtimeClasspath resolution, not just test-fabric where it was reported) -
fixed all six with the same runtimeLibrary(...) additions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…tonecutter
Stonecutter's nested per-version project layout broke several things that
keyed off the pre-migration flat project names:
- Maven publish's artifactId was "1.21.1" for every module (not just the
intended -fabric/-datagen-common/etc. suffix missing) - the artifactId
assignment ran before base.archivesName reached its final value. Moved it
into afterEvaluate{}. Also fixed the archie-test exclusion, which checked
project.name (now always "1.21.1") instead of project.path.
- modfusioner's fusejars task silently no-op'd ("No projects were found")
since it resolves projects by bare Project.name, and every Stonecutter tree
now has a leaf literally named "fabric"/"neoforge". Anchored it on the
unique ":core" container project and override inputFile via
gradle.projectsEvaluated once the real remapJar output paths are known.
- Dokka's per-module aggregation dependency block had been commented out
during the migration (stale flat project paths) - rebuilt against
Stonecutter's real :tree:branch:version paths.
- gameVersions in the publisher{} block now derives from
libs.versions.minecraft instead of a separately hardcoded "1.21.1" literal.
Verified: generatePomFileForMavenPublication produces correct artifactIds,
test tree is excluded, fusejars produces a real merged jar (both
fabric.mod.json and neoforge.mods.toml present), dokka configuration
resolves all 9 module paths, and publishCurseforge/publishModrinth dry-run
(debug=true) cleanly against live CurseForge/Modrinth data.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WW8YqJDBH8AFaTFirpCQGZ
@KP2048
KP2048 merged commit c35a245 into mainAug 29, 2026
1 of 2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Feature/stonecutter migration - #21

Merged
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration
Aug 29, 2026
Merged

Feature/stonecutter migration#21
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration

Conversation

@KP2048

Copy link
Copy Markdown
Member

No description provided.

KP2048and others added 5 commits August 28, 2026 16:06
Prerequisite for adding Stonecutter, which refuses to apply below
Gradle 9 (checked directly: 0.8.4, 0.9.1, and 0.9.7 all reject 8.x).
Verified clean on 9.7.1 first - full compile, unit tests, and the
whole task graph (Loom, Architectury, Dokka, ModFusioner, ModPublisher,
Shadow, the actualizer/archie plugins) all configure and run across
every module with no changes beyond the two below.
- Gradle 9 stopped bundling its own JUnit Platform launcher for
useJUnitPlatform() - added junit-platform-launcher to the catalog
and wired it once as testRuntimeOnly in the shared subprojects{}
dependencies block.
- core/common's verifyGuiSpriteAssets task used the `by registering {}`
delegate, deprecated in 9.6 and removed in 10 - switched to
`register("...")`.
architectury-loom's pinned version also now reads 1.17.491 instead of
1.13.469 in gradle/libs.versions.toml. This wasn't a deliberate edit -
noticed the file already showed 1.17.491 when checked, with no edit
made by this work to explain it. Left as-is since it's what actually
resolved and ran successfully throughout verification, but flagging it
since its cause is unexplained.
Converts core/{common,fabric,neoforge} to a Stonecutter-managed tree/branch
structure (settings.gradle.kts: stonecutter { create("core") { branch(...) } }),
keeping datagen/gametest/test on the old includeModule() scheme until this
slice is proven out.
Root build.gradle.kts guards subprojects{}/allprojects{} plugin application
against Stonecutter's synthetic tree/branch container projects (:core,
:core:common, etc. - real leaf projects nest under them and must not get
build plugins applied directly).
Sibling-project references (fabric/neoforge -> common) go through Stonecutter's
node.sibling("common").project API rather than a hardcoded project path -
ProjectNode.project resolves straight to the sibling's Gradle Project.
The old namedElements/transformProductionX cross-project dependency (Loom's
own common() mechanism) produces a circular task dependency under Stonecutter's
nested per-version project paths, so fabric/neoforge instead depend directly
on common's own "jar" task output as a FileCollection. (A plain SourceSetOutput
FileCollection almost works the same way, but breaks shadowJar - Shadow's copy
action expects zip-safe entries, not raw class/resource directories.)
Also bumps the Shadow plugin from com.github.johnrengelman.shadow 8.1.1 to the
maintained com.gradleup.shadow 9.6.1 fork - the old one is incompatible with
Gradle 9.7.1 (MissingPropertyException: mode in ShadowCopyAction), independent
of the Stonecutter migration itself.
Disables the background-session worktree-isolation guard for this repo
(.claude/settings.json) at the user's request.
Verified: :core:{common,fabric,neoforge}:1.21.1:assemble all succeed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
Extends the core-only Stonecutter validation slice to datagen, gametest, and
test - all four module trees are now Stonecutter-managed. settings.gradle.kts
registers all four trees identically (branch("common")/branch("fabric")/
branch("neoforge"), single version "1.21.1" each); each tree gets its own
stonecutter.gradle.kts (mirroring core's).
Sibling-project references follow the pattern established for core:
- Same-tree (X:common <-> X:fabric/neoforge): node.sibling("common").project.
- Cross-tree (e.g. datagen -> core, test -> core/datagen/gametest): Stonecutter
has no public cross-tree lookup API (node.sibling() only searches its own
tree), so these resolve via rootProject.project(":tree:branch:$version").
- Every cross-project compiled-output dependency goes through the sibling's
plain "jar" task output as a FileCollection, not project(path, configuration)
or a bare project(path) - both trigger a circular compileJava<->compileKotlin
task dependency under Stonecutter's nested per-version project paths,
confirmed live across multiple project-pairings (common<->common,
loader<->loader, common-mode<->loader). Deliberately not remapJar's output:
that transforms named->intermediary for shipping and reintroduces the same
class duplication one layer down (confirmed live: a Font/class_327
duplicate-overload regression in already-working core code, traced to a
poisoned shared .gradle/loom-cache/remapped_mods/ entry - cleared as part of
this work).
files() dependencies carry no transitive module metadata, unlike the
project(path, "namedElements") dependencies they replace, so every affected
common-mode project (datagen/gametest/test's common modules) repeats
whatever api/modApi surface its own code actually needs from its sibling
(Compose, kotlinx.serialization, storage lib) - verified by removing each
speculatively-added line and confirming the build still needs it before
keeping it (e.g. libs.rei.common was not actually needed by datagen-common).
The actualizer merges each common module's own source directly into its
fabric/neoforge siblings' compilation (not just their compiled output), so
those loader projects need common's compile-time deps directly too - same
reasoning, same fix.
gametest-neoforge needed the loader-specific libs.storage.neoforge instead of
libs.storage.common - NeoForge's remap pipeline doesn't handle
earth.terrarium.common_storage_lib's common artifact correctly (same family
of gap as the documented Cloche NeoForge remapCommon limitation for this
library); using the common variant surfaced as an ambiguous ItemResource.of
overload resolving against raw Fabric intermediary-mapped parameter types.
Verified: `./gradlew assemble` succeeds for the whole repo (all 12
common/fabric/neoforge modules across core/datagen/gametest/test).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…est/test loader modules
The files()-based cross-tree dependency on each core-{fabric,neoforge}
sibling (used to dodge the circular compileJava<->compileKotlin task
dependency documented in the previous commit) carries no runtime GAMELIBRARY
discovery either, same as it carries no compile-time transitive metadata.
core-fabric/core-neoforge each bundle the kotlinx.serialization format
add-ons (nbt/toml/json5) via bundleRuntimeLibrary - Archie's own Config
system needs all three at init - but that never propagated to any of
datagen/gametest/test's loader modules, which only had Compose repeated so
far.
Confirmed live via `./gradlew :test:fabric:1.21.1:runClient`:
Caused by: java.lang.NoClassDefFoundError: io/github/xn32/json5k/ConfigBuilder
at ...Json5ConfigSerializer.<clinit>
at ...ConfigSpec.<init>
at ...Archie.init
Same gap existed on datagen-fabric, datagen-neoforge, gametest-fabric,
gametest-neoforge, and test-neoforge (verified via each module's own
runtimeClasspath resolution, not just test-fabric where it was reported) -
fixed all six with the same runtimeLibrary(...) additions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…tonecutter
Stonecutter's nested per-version project layout broke several things that
keyed off the pre-migration flat project names:
- Maven publish's artifactId was "1.21.1" for every module (not just the
intended -fabric/-datagen-common/etc. suffix missing) - the artifactId
assignment ran before base.archivesName reached its final value. Moved it
into afterEvaluate{}. Also fixed the archie-test exclusion, which checked
project.name (now always "1.21.1") instead of project.path.
- modfusioner's fusejars task silently no-op'd ("No projects were found")
since it resolves projects by bare Project.name, and every Stonecutter tree
now has a leaf literally named "fabric"/"neoforge". Anchored it on the
unique ":core" container project and override inputFile via
gradle.projectsEvaluated once the real remapJar output paths are known.
- Dokka's per-module aggregation dependency block had been commented out
during the migration (stale flat project paths) - rebuilt against
Stonecutter's real :tree:branch:version paths.
- gameVersions in the publisher{} block now derives from
libs.versions.minecraft instead of a separately hardcoded "1.21.1" literal.
Verified: generatePomFileForMavenPublication produces correct artifactIds,
test tree is excluded, fusejars produces a real merged jar (both
fabric.mod.json and neoforge.mods.toml present), dokka configuration
resolves all 9 module paths, and publishCurseforge/publishModrinth dry-run
(debug=true) cleanly against live CurseForge/Modrinth data.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WW8YqJDBH8AFaTFirpCQGZ
@KP2048
KP2048 merged commit c35a245 into mainAug 29, 2026
1 of 2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Feature/stonecutter migration - #21

Merged
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration
Aug 29, 2026
Merged

Feature/stonecutter migration#21
KP2048 merged 5 commits into
mainfrom
feature/stonecutter-migration

Conversation

@KP2048

Copy link
Copy Markdown
Member

No description provided.

KP2048and others added 5 commits August 28, 2026 16:06
Prerequisite for adding Stonecutter, which refuses to apply below
Gradle 9 (checked directly: 0.8.4, 0.9.1, and 0.9.7 all reject 8.x).
Verified clean on 9.7.1 first - full compile, unit tests, and the
whole task graph (Loom, Architectury, Dokka, ModFusioner, ModPublisher,
Shadow, the actualizer/archie plugins) all configure and run across
every module with no changes beyond the two below.
- Gradle 9 stopped bundling its own JUnit Platform launcher for
useJUnitPlatform() - added junit-platform-launcher to the catalog
and wired it once as testRuntimeOnly in the shared subprojects{}
dependencies block.
- core/common's verifyGuiSpriteAssets task used the `by registering {}`
delegate, deprecated in 9.6 and removed in 10 - switched to
`register("...")`.
architectury-loom's pinned version also now reads 1.17.491 instead of
1.13.469 in gradle/libs.versions.toml. This wasn't a deliberate edit -
noticed the file already showed 1.17.491 when checked, with no edit
made by this work to explain it. Left as-is since it's what actually
resolved and ran successfully throughout verification, but flagging it
since its cause is unexplained.
Converts core/{common,fabric,neoforge} to a Stonecutter-managed tree/branch
structure (settings.gradle.kts: stonecutter { create("core") { branch(...) } }),
keeping datagen/gametest/test on the old includeModule() scheme until this
slice is proven out.
Root build.gradle.kts guards subprojects{}/allprojects{} plugin application
against Stonecutter's synthetic tree/branch container projects (:core,
:core:common, etc. - real leaf projects nest under them and must not get
build plugins applied directly).
Sibling-project references (fabric/neoforge -> common) go through Stonecutter's
node.sibling("common").project API rather than a hardcoded project path -
ProjectNode.project resolves straight to the sibling's Gradle Project.
The old namedElements/transformProductionX cross-project dependency (Loom's
own common() mechanism) produces a circular task dependency under Stonecutter's
nested per-version project paths, so fabric/neoforge instead depend directly
on common's own "jar" task output as a FileCollection. (A plain SourceSetOutput
FileCollection almost works the same way, but breaks shadowJar - Shadow's copy
action expects zip-safe entries, not raw class/resource directories.)
Also bumps the Shadow plugin from com.github.johnrengelman.shadow 8.1.1 to the
maintained com.gradleup.shadow 9.6.1 fork - the old one is incompatible with
Gradle 9.7.1 (MissingPropertyException: mode in ShadowCopyAction), independent
of the Stonecutter migration itself.
Disables the background-session worktree-isolation guard for this repo
(.claude/settings.json) at the user's request.
Verified: :core:{common,fabric,neoforge}:1.21.1:assemble all succeed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
Extends the core-only Stonecutter validation slice to datagen, gametest, and
test - all four module trees are now Stonecutter-managed. settings.gradle.kts
registers all four trees identically (branch("common")/branch("fabric")/
branch("neoforge"), single version "1.21.1" each); each tree gets its own
stonecutter.gradle.kts (mirroring core's).
Sibling-project references follow the pattern established for core:
- Same-tree (X:common <-> X:fabric/neoforge): node.sibling("common").project.
- Cross-tree (e.g. datagen -> core, test -> core/datagen/gametest): Stonecutter
has no public cross-tree lookup API (node.sibling() only searches its own
tree), so these resolve via rootProject.project(":tree:branch:$version").
- Every cross-project compiled-output dependency goes through the sibling's
plain "jar" task output as a FileCollection, not project(path, configuration)
or a bare project(path) - both trigger a circular compileJava<->compileKotlin
task dependency under Stonecutter's nested per-version project paths,
confirmed live across multiple project-pairings (common<->common,
loader<->loader, common-mode<->loader). Deliberately not remapJar's output:
that transforms named->intermediary for shipping and reintroduces the same
class duplication one layer down (confirmed live: a Font/class_327
duplicate-overload regression in already-working core code, traced to a
poisoned shared .gradle/loom-cache/remapped_mods/ entry - cleared as part of
this work).
files() dependencies carry no transitive module metadata, unlike the
project(path, "namedElements") dependencies they replace, so every affected
common-mode project (datagen/gametest/test's common modules) repeats
whatever api/modApi surface its own code actually needs from its sibling
(Compose, kotlinx.serialization, storage lib) - verified by removing each
speculatively-added line and confirming the build still needs it before
keeping it (e.g. libs.rei.common was not actually needed by datagen-common).
The actualizer merges each common module's own source directly into its
fabric/neoforge siblings' compilation (not just their compiled output), so
those loader projects need common's compile-time deps directly too - same
reasoning, same fix.
gametest-neoforge needed the loader-specific libs.storage.neoforge instead of
libs.storage.common - NeoForge's remap pipeline doesn't handle
earth.terrarium.common_storage_lib's common artifact correctly (same family
of gap as the documented Cloche NeoForge remapCommon limitation for this
library); using the common variant surfaced as an ambiguous ItemResource.of
overload resolving against raw Fabric intermediary-mapped parameter types.
Verified: `./gradlew assemble` succeeds for the whole repo (all 12
common/fabric/neoforge modules across core/datagen/gametest/test).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…est/test loader modules
The files()-based cross-tree dependency on each core-{fabric,neoforge}
sibling (used to dodge the circular compileJava<->compileKotlin task
dependency documented in the previous commit) carries no runtime GAMELIBRARY
discovery either, same as it carries no compile-time transitive metadata.
core-fabric/core-neoforge each bundle the kotlinx.serialization format
add-ons (nbt/toml/json5) via bundleRuntimeLibrary - Archie's own Config
system needs all three at init - but that never propagated to any of
datagen/gametest/test's loader modules, which only had Compose repeated so
far.
Confirmed live via `./gradlew :test:fabric:1.21.1:runClient`:
Caused by: java.lang.NoClassDefFoundError: io/github/xn32/json5k/ConfigBuilder
at ...Json5ConfigSerializer.<clinit>
at ...ConfigSpec.<init>
at ...Archie.init
Same gap existed on datagen-fabric, datagen-neoforge, gametest-fabric,
gametest-neoforge, and test-neoforge (verified via each module's own
runtimeClasspath resolution, not just test-fabric where it was reported) -
fixed all six with the same runtimeLibrary(...) additions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkTGULzd3V7X4ZGP3iw7P
…tonecutter
Stonecutter's nested per-version project layout broke several things that
keyed off the pre-migration flat project names:
- Maven publish's artifactId was "1.21.1" for every module (not just the
intended -fabric/-datagen-common/etc. suffix missing) - the artifactId
assignment ran before base.archivesName reached its final value. Moved it
into afterEvaluate{}. Also fixed the archie-test exclusion, which checked
project.name (now always "1.21.1") instead of project.path.
- modfusioner's fusejars task silently no-op'd ("No projects were found")
since it resolves projects by bare Project.name, and every Stonecutter tree
now has a leaf literally named "fabric"/"neoforge". Anchored it on the
unique ":core" container project and override inputFile via
gradle.projectsEvaluated once the real remapJar output paths are known.
- Dokka's per-module aggregation dependency block had been commented out
during the migration (stale flat project paths) - rebuilt against
Stonecutter's real :tree:branch:version paths.
- gameVersions in the publisher{} block now derives from
libs.versions.minecraft instead of a separately hardcoded "1.21.1" literal.
Verified: generatePomFileForMavenPublication produces correct artifactIds,
test tree is excluded, fusejars produces a real merged jar (both
fabric.mod.json and neoforge.mods.toml present), dokka configuration
resolves all 9 module paths, and publishCurseforge/publishModrinth dry-run
(debug=true) cleanly against live CurseForge/Modrinth data.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WW8YqJDBH8AFaTFirpCQGZ
@KP2048
KP2048 merged commit c35a245 into mainAug 29, 2026
1 of 2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@KP2048