Skip to content

build: collapse Archie/Archie-Core/Archie-Test into one Loom build at repo root - #15

Open
KP2048 wants to merge 7 commits into
1.21.xfrom
worktree-archie-core-cloche-migration
Open

build: collapse Archie/Archie-Core/Archie-Test into one Loom build at repo root#15
KP2048 wants to merge 7 commits into
1.21.xfrom
worktree-archie-core-cloche-migration

Conversation

@KP2048

@KP2048 KP2048 commented Aug 11, 2026

Copy link
Copy Markdown
Member

Summary

Finishes the archie-core modularization effort: stands up archie-core/archie-datagen/archie-gametest as Architectury Loom modules (after Cloche turned out to have a structural NeoForge remapCommon gap), then collapses the repo's old three-way split (Archie/ + Archie-Core/ + Archie-Test/, wired together by a Gradle composite build) into one unified Loom build at the repo root.

What changed

  • archie-core (core/{common,fabric,neoforge}): today's library, ported mechanically from Archie/{common,fabric,neoforge}.
  • archie-datagen (datagen/{common,fabric,neoforge}): the datagen DSL, split out as its own separate mod (archie_datagen) - dev-time only, never shipped in a production jar.
  • archie-gametest (gametest/{common,fabric,neoforge}): the GameTest framework/harness, also its own separate mod (archie_gametest) - dev/test-time only.
  • archie-test (test/{common,fabric,neoforge}): the dev-playground mod, folded in from the old Archie-Test/ composite build, now a plain sibling module depending on the other three via modApi(project(":x")).
  • Archie.kt's hard dependency on datagen/gametest is inverted into a ServiceLoader-based ArchieExtension hook - archie-core has no compile-time dependency on either.
  • Repo root is now archie-core's own build (rootProject.name = "Archie"); the old Archie/, Archie-Test/, and Archie-Core/ directories are gone.
  • Docs (Dokka + MkDocs), the merged-jar (modfusioner, core-only), mod publishing (modpublisher), and per-module Maven publishing (Reposilite, core/datagen/gametest only) are all wired into the new root build.
  • CI workflows, README.md, AGENTS.md, and the sync-docs-after-overhaul skill updated for the new flat module layout.

Verification

  • ./gradlew build -x test succeeds clean across all 12 modules (core/datagen/gametest/test × common/fabric/neoforge).
  • ./gradlew fusejars produces a core-only merged jar (both fabric.mod.json and neoforge.mods.toml present, no datagen/gametest/test content).
  • ./gradlew publishToMavenLocal publishes exactly the 9 expected artifacts (core/datagen/gametest × common/fabric/neoforge), zero archie-test-* ones.
  • Full GameTest suite has not been run in CI as part of this PR - CI's check job will exercise that on push.

🤖 Generated with Claude Code

KP2048 and others added 4 commits August 10, 2026 16:08
Phase 1 of the Archie modularization plan: port today's common+fabric+
neoforge into a new archie-core (Archie-Core/core/{common,fabric,neoforge}),
with the hard gametest/datagen dependency inverted into a ServiceLoader-based
ArchieExtension registration hook instead of Archie.kt reaching into them
directly.

Directory layout (nested <module>/<platform>, flattened to hyphenated Gradle
project names) matches terrarium-earth/Common-Storage-Lib's settings.gradle.kts
convention, so archie-datagen/archie-gametest (and eventually the test mod)
can join later as more includeModule(...) calls without another restructure.

This also closes out a from-scratch Cloche migration spike (fully reverted
here): Cloche got archie-core's Fabric target to a clean, fully verified build
(compile + full jar/remap pipeline), but NeoForge hit a confirmed structural
gap in Cloche 0.19.13 - FabricTargetImpl has a dedicated remapCommon pipeline
for intermediary-mapped "common" mod-library dependencies that
ForgeLikeTargetImpl/NeoForgeTargetImpl simply doesn't have yet, so a real,
load-bearing common dependency (Common Storage Lib) can never be remapped
correctly for NeoForge under today's Cloche. Revisiting Cloche later, once
that gap is fixed upstream, remains straightforward given this module
boundary already exists.

Verified: :archie-core-common, :archie-core-fabric, and :archie-core-neoforge
all build cleanly end to end (compile, remapJar, shadowJar, assemble).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ports the old Archie/common+fabric+neoforge's data and gametest packages
onto their own Cloche-style nested modules (datagen/{common,fabric,neoforge},
gametest/{common,fabric,neoforge}), matching archie-core's Loom layout and
Common-Storage-Lib's flattened project-naming convention.

- Dissolves AEvents into ADatagenEvents (archie-datagen-common) and
  AGametestEvents (archie-gametest-common); generic event-wrapper plumbing
  (Handler/HandlerConstructor/AEventObject) stays in archie-core.
- Datagen/gametest each ship as their own separate mod (own modId, own
  fabric.mod.json/neoforge.mods.toml, own mixins.json), triggering
  registration flush directly via their own mixins - no ArchieExtension
  dependency inversion needed for the trigger point itself.
- Adds an ArchieExtension ServiceLoader hook implementation in each new
  module (DatagenArchieExtension/GametestArchieExtension) so Archie.kt's
  existing onDataGen()/onGameTest() calls activate ArchieDatagen/
  ArchieGameTestwhen those modules are present, with no compile-time
  dependency from archie-core onto either.
- Splits AConditionsPlatform: register()/codec() (runtime condition
  registration, needed by Archie.kt) stay in archie-core; withCondition()/
  fabricRecipeProvider() (datagen-only, reference the datagen-only
  ARecipeProvider type) move to a new ADatagenConditionsPlatform in
  archie-datagen.
- Moves conditions/ingredients/ACommonTags to archie-core (Archie.kt calls
  ABuiltinConditions.init()/ABuiltinIngredients.init()/ACommonTags.init()
  directly), and data/internal + gametest/internal (Archie's own dogfooded
  datagen providers and self-test GameTest suite) to their respective new
  modules.
- Widens ComposeIdleAware/ComposeTestClockOverride from internal to public
  in archie-core so archie-gametest's client harness can reach them across
  the module boundary.

Verified: full `./gradlew build -x test` succeeds across all 9 modules
(archie-core/-datagen/-gametest x common/fabric/neoforge).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Finalizes the archie-core migration: archie-core's Loom-based build (from
Archie-Core/) now IS the repo root, replacing the old Gradle composite build
that wired together separate Archie/ and Archie-Test/ builds via includeBuild.

- Folds Archie-Test in as a fourth product, archie-test-{common,fabric,
  neoforge}, using the exact same nested-module convention as core/datagen/
  gametest - depends on the other three via plain project references
  (modApi(project(":archie-core-fabric")) etc.) instead of the old
  composite-build dependencySubstitution + raw "net.kernelpanicsoft:common"
  coordinate trick. AEvents references in its GameTest suite (stale from
  before AEvents was dissolved into ADatagenEvents/AGametestEvents) fixed
  along the way.
- Wires in the dev.opensavvy.dokka-mkdocs docs pipeline at the new root
  (dokka(project(":archie-core-common")) etc. aggregation, embedDokkaInto-
  MkDocs, publishDocs/generateChangelog tasks) and ports mkdocs.yml + docs/
  + CHANGELOG.md up from the old Archie/ root, fixing the mkdocs edit_uri
  path. modfusioner/modpublisher (CurseForge/Modrinth publishing, merged-jar
  fusion) are NOT ported yet - noted as a known gap in AGENTS.md.
- Moves archie-core's settings.gradle.kts/build.gradle.kts/gradle.properties/
  gradlew/wrapper up to become the repo's own; settings.gradle.kts's version
  catalog now resolves gradle/libs.versions.toml via Gradle's own default-
  location convention (dropped the now-redundant explicit
  dependencyResolutionManagement block, which double-registered it).
  rootProject.name -> "Archie".
- Deletes the old Archie/, Archie-Test/, and now-empty Archie-Core/
  directories entirely.
- Updates .github/workflows/{check,docs,release-notes}.yaml,
  .github/scripts/generate_release_notes.py, README.md, AGENTS.md, and the
  sync-docs-after-overhaul skill for the new flat module layout and paths.
- .gitignore: added a top-level .kotlin entry (the existing */.kotlin
  pattern only matched one level deep, missing the root-level .kotlin/ this
  layout now produces).

Verified: full `./gradlew build -x test` succeeds at the new root across all
12 modules (archie-core/-datagen/-gametest/-test x common/fabric/neoforge).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ports the remaining pieces of the old Archie/build.gradle.kts's release
pipeline that weren't part of the repo-collapse commit's scope:

- modfusioner: merges only archie-core-fabric's and archie-core-neoforge's
  remapJar outputs into one artifact (fusioner { fabric { projectName =
  "archie-core-fabric" }; neoforge { projectName = "archie-core-neoforge" } }).
  archie-datagen/-gametest/-test are never fused - each ships as its own
  separate mod. build/assemble are finalizedBy(fusejars). Verified: fusejars
  alone produces build/artifacts/archie-core-merged-*.jar with both
  fabric.mod.json and neoforge.mods.toml, nothing else pulled in.
- modpublisher: publisher{} block ported verbatim (CurseForge/Modrinth/
  GitHub IDs, deps, artifact = tasks.fusejars.get()); publishCurseforge/
  publishModrinth/publishGitHub/publishMod each dependsOn(generateChangelog).
- Per-module Maven publishing to kernelpanicsoft.net's Reposilite: one
  MavenPublication per archie-core/-datagen/-gametest module (archie-test
  excluded - dev playground, never published), wired via
  extensions.configure<PublishingExtension>("publishing") { ... } inside
  subprojects{} - the bare publishing { } DSL accessor isn't type-safe here
  since maven-publish is applied imperatively in the same script, not via a
  plugins{} block (confirmed by mirroring old Archie's own root
  build.gradle.kts, which hit the identical issue once already). Verified
  via publishToMavenLocal: exactly the 9 expected artifacts, zero
  archie-test-* ones.
- Dropped the older, superseded root-level "mavenJava" publishing setup
  that existed alongside the newer per-module one in old Archie/
  build.gradle.kts (different repo, different credentials convention) -
  the per-module one was the more recent, more specific mechanism.

Verified: full ./gradlew build -x test still succeeds at the root across
all 12 modules with dokka/mkdocs/fusioner/publisher/maven-publish wired in
together.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 11, 2026 02:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@KP2048 KP2048 changed the title Collapse Archie/Archie-Core/Archie-Test into one Loom build at repo root build: collapse Archie/Archie-Core/Archie-Test into one Loom build at repo root Aug 11, 2026
KP2048 and others added 3 commits August 10, 2026 23:11
…st/-test

CI's check job (#15) failed on a genuinely
from-scratch checkout with:

  A problem occurred configuring project ':archie-datagen-common'.
  > Failed to setup Minecraft, java.io.UncheckedIOException: Failed to
    read metadata from core/common/build/libs/archie-core-common-1.0.0.jar

Root cause: every cross-product dependency in datagen/gametest/test's
build.gradle.kts files used modApi(project(":archie-core-*")) (and
similarly for datagen/gametest from test). mod* configurations mark a
dependency as needing Loom's intermediary<->named remapping - for a
project(...) reference, that makes Loom eagerly read the target project's
own output jar during *configuration*, before any task has executed. On a
clean checkout that jar can't possibly exist yet, and no task ordering
within one Gradle invocation can fix a configuration-time file read
(confirmed: even `./gradlew help` alone fails this way). None of these
cross-product dependencies need remapping at all - every product's fabric
target is already namespace-symmetric with every other product's fabric
target (same for neoforge/common), matching this session's original
common-to-common design intent.

Fix: replaced all 11 modApi(project(":archie-x-y")) call sites with plain
api(project(":archie-x-y", "namedElements")) - the explicit "namedElements"
target matters (a bare api(project(":x")) reintroduces the separate,
already-solved transformProductionFabric/NeoForge "Type ... not present"
issue that modApi was originally reached for). Deliberately did NOT add
isTransitive = false to these calls (copied by habit from an unrelated
custom-configuration pattern elsewhere in this build) - it strips the
target project's own api-declared dependencies (compose.runtime,
kotlinx-serialization) from flowing through, breaking compilation.

Also reverts the "build archie-core first" CI workaround steps added
while chasing a wrong initial diagnosis (a coincidental, non-reproducible
"dirty cache" theory) - unnecessary now that the real dependency-shape bug
is fixed.

Verified: full ./gradlew build -x test, publishToMavenLocal, and fusejars
all succeed from a completely clean checkout state (*/build/ + .gradle +
.kotlin all removed beforehand) across all 12 modules.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…itPlatform()

Old Archie/common/src/test/ had 13 real JUnit5 unit test classes plus its
own GameTests.kt (a @testfactory dispatching real GameTest runs, same
shape as archie-test's own) - none of it ever got ported when archie-core
was first stood up on Loom. This was silent locally because -x test skips
the test task but not compileTestKotlin, and even compileTestKotlin alone
doesn't catch a missing useJUnitPlatform() (compiles fine, discovers 0
tests at execution time) - only actually running the test task and
checking for real JUnit XML output surfaced it.

- Ported the 13 plain unit tests straight to core/common/src/test/ (none
  reference gametest - just core's own gui/networking/util packages).
- Moved GameTests.kt to gametest/common/src/test/ instead - it needs
  archie-gametest-common's own `internal fun archieGameTests()`, which a
  different module's test sourceSet can't see. Fixed its stale AEvents
  reference (-> AGametestEvents) along the way, the same class of
  leftover reference this session's earlier datagen/gametest work fixed
  repeatedly - this exact file just hadn't been grepped yet.
- core/common/build.gradle.kts had no `test { useJUnitPlatform() }` at
  all - a pre-existing gap, not new this session. Added it.
  gametest/common/build.gradle.kts got the full test{} block (the
  archie.junit.gametest.matrix systemProperty wiring GameTests.kt needs)
  ported from old Archie/common/build.gradle.kts verbatim.
- junit-platform.properties (parallel-execution tuning GameTests.kt's
  @execution(CONCURRENT) needs) copied to both core/common/src/test/
  resources/ and gametest/common/src/test/resources/.

Verified: :archie-core-common:test actually executes and passes all 13
test classes (real JUnit XML tests="13 files" failures="0" errors="0"
counts, not just a green task), and a full ./gradlew build -x test
compileTestKotlin still succeeds from a completely clean checkout state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…od filter

CI's check job got further this time (past config, past compilation, into
actually running real GameTests) and surfaced three more real bugs, found
by literally running the GameTest suite locally instead of reasoning
about it:

1. GameTestGradleInvocation.taskPath hardcoded the old composite-build
   task paths :fabric:runGametest/:neoforge:runGametest - stale from
   before the repo collapse, when archie-gametest and archie-test each
   had their own separate workspace root with its own bare :fabric
   project. Now both call through the same shared JUnit bridge but need
   different target projects (archie-gametest-fabric vs
   archie-test-fabric). Added a projectPrefix parameter threaded through
   GameTestRunner.tests(modID, projectPrefix, tests) ->
   GameTestGradleInvocation.parseMatrix -> taskPath (now
   :$projectPrefix-$loader:runGametest), updated both GameTests.kt call
   sites accordingly.

2. archie-gametest/-datagen's fabric/neoforge dev run configs
   (runGametest/runDatagen) crashed with NoClassDefFoundError:
   me/shedaniel/math/Color - archie-core's BuiltinSerializers.kt touches
   cloth-config's Color class unconditionally at class-init time even
   though cloth-config is compileOnly in the shipped jar. Old
   Archie/fabric and Archie/neoforge's own dev runs papered over this
   with modLocalRuntime/modRuntimeOnly(libs.clothConfig.*) - ported
   correctly to core and test already, but missed on datagen/gametest's
   own fabric+neoforge modules, whose dev runs also load archie-core as
   a mod dependency. Added the same dependency to all four.

3. archie-gametest-fabric/-neoforge's own gametest run config filtered
   by mod id "archie_gametest", but ArchieGameTest registers its tests
   under Archie.MOD ("archie", the library's own id) - matching old
   Archie/fabric's own run config, which always used mod_id ("archie"),
   never anything gametest-specific. Filtering by archie_gametest found
   zero tests. My own mistake writing this run config earlier this
   session, not an upstream porting error. Fixed to filter by "archie".

Verified end to end, not just build-succeeded: :archie-gametest-common:test
and :archie-test-common:test, each with
-Darchie.junit.gametest.matrix=fabric:server, genuinely launch a real
Minecraft server subprocess, run real @gameTest methods, and report
failures="0" errors="0" in their JUnit XML output. Full ./gradlew build -x
test compileTestKotlin still succeeds from a completely clean checkout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to 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.

2 participants