Skip to content

Add DevCenter.getSpec() returning a versioned JSON description#76

Merged
jkschneider merged 1 commit into
mainfrom
devcenter-getspec
May 12, 2026
Merged

Add DevCenter.getSpec() returning a versioned JSON description#76
jkschneider merged 1 commit into
mainfrom
devcenter-getspec

Conversation

@jkschneider
Copy link
Copy Markdown
Member

Summary

  • Adds String getSpec() to io.moderne.devcenter.DevCenter, returning a versioned JSON description of the devcenter's cards and measures.
  • Lets consumers (the Moderne CLI) read DevCenter structure without sharing Java class identity across classloaders. The CLI today bundles this artifact in its fat jar to wire DevCenter into parent classpath; that bundling causes class-identity splits and shadows customer-provided rewrite-devcenter versions. JSON-over-reflection is the contract that lets the CLI unbundle.

Schema (v1)

{
  "apiVersion": "v1",
  "upgradesAndMigrations": [
    {"name": "...", "fixRecipeId": "...", "measures": ["...", ...]},
    ...
  ],
  "security": {"name": "...", "fixRecipeId": "...", "measures": [...]} | null
}

Card and measure ordering is preserved. fixRecipeId may be null. security is null when no security card is defined.

Test plan

  • getSpecMatchesStarterDevCenter — full structure round-trip against DevCenterStarter, including security card + measure ordering
  • getSpecOmitsSecurityWhenAbsent — nullable security handling
  • ./gradlew compileJava passes

Follow-up

The Moderne CLI side that consumes getSpec() is a separate PR in moderne-cli (depends on this artifact being released).

The Moderne CLI bundles `rewrite-devcenter` in its fat jar so it can
construct a `DevCenter` from a recipe and walk its cards/measures to
render dashboards. That bundling causes class-identity splits across
the CLI's recipe classloader boundary (e.g. `SemverRowBuilder$ParserHolder`
fails to initialize because the parent loader can't see `VersionParser`
from `rewrite-java-dependencies`) and shadows whatever
`rewrite-devcenter` version customer custom devcenters bring in.

`getSpec()` lets the CLI consume DevCenter structure as JSON instead of
walking the Java API across classloaders. The CLI reflectively
constructs `DevCenter`, calls `getSpec()`, and parses the result into
CLI-owned DTOs - no shared class identity needed.

Schema (v1):
- `apiVersion`: stable wire-format discriminator
- `upgradesAndMigrations`: ordered cards, each with name, fixRecipeId, measure names
- `security`: nullable security card with the same shape
@jkschneider jkschneider merged commit 20f000e into main May 12, 2026
1 check passed
@jkschneider jkschneider deleted the devcenter-getspec branch May 12, 2026 15:09
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.

1 participant