Skip to content

meta gen unions an ancestor .metaobjects/config.json into a sub-project's output (the gen-side remainder of #327) #340

Description

@dmealing

Found while evaluating 0.24.0-rc.7 in an adopter project. This is the gen-side remainder of
what #327 fixed for docs.

Summary

meta gen, run in a sub-project that has its own metaobjects.config.ts and its own
metaobjects/ source directory, now also generates from the sources declared in an ancestor
.metaobjects/config.json. The sub-project's output absorbs metadata belonging to unrelated
parts of the repository.

The hard failure from #326 is genuinely fixed — gen no longer errors out from a sub-project.
But the underlying behaviour that caused it, an ancestor config widening a sub-project's scope,
is still present here. #327 fixed the equivalent for meta docs, where an explicit positional
path made the over-reach easy to name; meta gen takes no path argument, so nothing scopes it.

Observed

Layout — a Maven-rooted monorepo whose web app is one of several metadata trees:

<repo-root>/
  .metaobjects/config.json      # sources: 4 trees (entities, ai-prompts, game-prompts, web-entities)
  <app>/
    metaobjects.config.ts       # outDir: ./src/generated
    metaobjects/                # the app's OWN metadata (19 packages)

Same tree, same command, run from <app>/:

CLI files generated
0.23.1 376
0.24.0-rc.7 831

The additions are not the app's own metadata. Spot-checked concretely:

  • AbilityGenerationPayload and AbilityGenerationResponse now emit into <app>/src/generated/.
  • Their only declaration is <ai-module>/src/main/resources/prompts/ability/meta.ability-generation.yaml.
  • grep -rl AbilityGenerationPayload <app>/metaobjects/ returns nothing — they are absent from
    the app's own source dir entirely.

These are server-side LLM prompt payload types. They have no client surface, and the web app
will never construct one.

Why it matters even though nothing breaks

tsc --noEmit passes and the app's tests pass, so this is bloat rather than breakage. But:

  • The generated tree more than doubles, and the surplus is the internal DTO vocabulary of a
    different module. Anything that walks src/generated — a barrel, a docs pass, a bundler
    analysis, a reviewer — now sees it.
  • It silently couples the web app's build output to a server module's prompt metadata. A prompt
    payload rename becomes a diff in the web app's generated tree.
  • The failure mode is invisible: no error, no warning, just a larger directory. An adopter who
    did not count files before and after would never notice.

Suggested fix

A sub-project that declares its own metaobjects.config.ts should generate from its own
sources. Treat an ancestor .metaobjects/config.json as the default for a project that has not
declared one, not as an addition to one that has.

If the union is intentional — a monorepo where every tree really should be visible everywhere —
it needs to be opt-in, or at least announced, since the only present symptom is a file count
nobody is watching.

Workaround for adopters today

Give the sub-project its own .metaobjects/config.json naming only its own source dir; the
upward walk stops there and the output returns to the expected set. Note this file is
.gitignored by the scaffolder in the projects checked, so it has to be un-ignored to reach CI.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions