diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d06b489a..10089c882 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -125,8 +125,56 @@ generator catalog and the Atlas evaluation are 1.2 work. pages `meta docs` writes) and `agent-docs` (the pages `meta docs --agent` writes), both neutral and both still run by `meta docs`; a `generators` entry naming either string is refused the way `"docs"` is. Java: `plantuml`, `html-docs`, `ai-docs`, `json-schema` and the - deprecated `mustache`, each by the class name a pom already uses. None of the seven ships - eject source yet; `mustache` will not. + deprecated `mustache`, each by the class name a pom already uses. `mustache` will not ship + eject source. The four Java generators that can ship it do: see **Java and Kotlin** below. + +- **Java and Kotlin: eject hands over the emitters a generator writes through, and + `api-docs`, `plantuml`, `html-docs`, `ai-docs` and `json-schema` are ejectable.** An ejected + Java or Kotlin generator used to be one file over packaged emitters, so a defect in the enum, + record-builder, extraction-mirror or prompt-format writers still waited for a release. Eject + now copies those emitters with the generator, into its package, and points the imports the + copies have of one another at the copies. Java `dto` and `value-object` take + `Fr019SharedEnum` and `SpringRecordBuilder`; Java `output-parser` takes `Fr019SharedEnum`; + Java `output-prompt` takes `OutputFormatSpecEmitter`; Kotlin `entity` takes + `KotlinEnumEmitter`; Kotlin `output-parser` takes `KotlinExtractSchemaEmitter`; Kotlin + `output-prompt` takes `KotlinOutputFormatSpecEmitter` and `KotlinExtractSchemaEmitter`. A + class two generators share is written once and never overwritten. The naming and type-mapping + tables, the model walks and the generator bases stay in the package as the engine. Kotlin + `Fr019SharedEnum` is engine: it writes nothing, and the type mapper takes its + `ProvidedEnumConfig` as an argument, so its `providedInDeclarationPackage` and + `DECLARATION_PACKAGE` members are now public. Packaged output is unchanged. A copy you ejected earlier keeps compiling with the packaged + emitters; own them with the recipe in + [own-your-codegen](docs/features/own-your-codegen.md#ejecting-a-generator-hands-over-the-emitters-it-writes-through-java-and-kotlin). + - **`api-docs` is a generator, and ejectable, in Java and Kotlin.** The api reference is + `JavaApiDocsGenerator` / `KotlinApiDocsGenerator`, a `` entry like any other: + `metaobjects:generate` runs it and `metaobjects:verify` checks it, with `outputDir`, + `apiSubDir`, `layout`, `projectName` and `modelBaseUrl` in its ``. It replaces the + `metaobjects:docs` goal (see **Removed**). Eject + copies the generator, the page model, the builder, the renderer and the path math into a + subpackage per port, `.apidocs.java` or `.apidocs.kotlin`: the two ports + name those classes alike, so one `codegen/` module can hold both without a class declared + twice. Eject prints the class name to list. Eject writes `codegen/pom.xml` for the ports + the module holds at that moment and never edits it afterwards. One call that ejects for + both ports now gets a pom that builds both source trees; it used to leave `src/main/java` + out. When a later call adds a port, the pom does not declare what that port needs (the + `metaobjects-codegen-*` dependency, `kotlin-maven-plugin`, or `src/main/java` as a source + root after a Kotlin-first eject), and eject now warns and prints what to add. For Java the page templates come too, into + `codegen/src/main/resources//apidocs/java/templates/`, with the copied + template provider pointed there. What the Java reference documents is still what the + packaged generators emit for (`GeneratorApplicability.packaged()`): an owned `routes` whose + `appliesTo` you changed is documented as the packaged one behaves, unless you change the + line of your `JavaApiDocsGenerator` copy that builds it. The pages are the ones 8.0's + docs goal wrote, given the same options. + - **The Java `plantuml`, `html-docs`, `ai-docs` and `json-schema` generators ship eject + source**, each with the writer that emits its file. `SingleHtmlDirectGeneratorBase` now + drives the new `HtmlDirectWriter`, as the JSON base drives `JsonDirectWriter`, so a copied + HTML generator pairs with the copy of its writer. A subclass that overrode + `writeHtml(MetaDataHtmlDocumentationWriter)` keeps being called, through a deprecated bridge the + base still calls; one that returns the stock writer from `getWriter` still compiles. A subclass + compiled against 1.0.x needs a recompile, because the method's return type changed. The attributes the JSON Schema and AI documentation generators + add to the metamodel moved to `CodeGenMetaDataProvider`, where the loader registers them, + so a copy owns emit code only; the old static methods and constants on the two generators + stay as deprecated forwarders. - **The Java `entity` and `extractor` generators can be ejected.** `mvn metaobjects:eject -Dnames=entity,extractor -Dport=java` copies each generator, with @@ -139,25 +187,21 @@ generator catalog and the Atlas evaluation are 1.2 work. Amendment 6. - **The owned `entity` includes the class body.** Eject copies seven files into one package: `JavaObjectCodeGenerator`, the two bases it extends (`JavaCodeGenerator`, - `BaseObjectCodeGenerator`), and the four writers that emit each class + `BaseObjectCodeGenerator`) and the four writers that emit each class (`BaseObjectCodeWriter`, `JavaCodeWriter`, `PojoAwareCodeWriter`, `ValueObjectCodeWriter`). The copies use one another, never the packaged classes: where one imports another, eject rewrites that import along with the package line. You change a field, a constructor or an accessor by editing the writer, with nothing to subclass. `-Dlist` gives `entity` one verdict over all seven files. Details: [own-your-codegen](docs/features/own-your-codegen.md#java-entity-and-extractor). - - **`extractor` is a generator of its own (Java).** `ExtractorCodeGenerator` can be named + - **`extractor` is a generator of its own (Java).** `ExtractorCodeGenerator` is named in ``, with the same `outputDir`, `pkgPrefix`, `pkgSuffix`, `namePrefix`, - `nameSuffix` and `` as your `entity` generator. When it is, the plugin sets - `emitExtractors=false` on `entity`, so each `Extractor` has one emitter; an - `emitExtractors=true` in the pom does not override that. Outside Maven, set the arg - yourself. Ejecting it also copies `JavaCodeWriter` and `BaseObjectCodeWriter`, where it - reads class names from. In the same package as an owned `entity`, the two share that - one copy. - - **A pom that wires only `entity` still writes the extractors.** Its class files change - once, in the header comment only: see **Changed** below. - - New public API: in `metaobjects-codegen-base`, the `EmitsObjectExtractors` marker, whose - `ARG_EMIT_EXTRACTORS` names the `emitExtractors` arg; in `metaobjects-codegen-spring`, + `nameSuffix` and `` as your `entity` generator, and it is the one generator that + writes `Extractor` classes (see **Removed**). Ejecting it also copies `JavaCodeWriter` and `BaseObjectCodeWriter`, where it + reads class names from. In the same package as an owned `entity`, the two share those + writers. + - **`entity`'s class files change once**, in the header comment only: see **Changed** below. + - New public API: in `metaobjects-codegen-spring`, `GeneratorRegistry.GeneratorInfo.ejectWith()`, the classes eject copies with a generator. @@ -947,6 +991,29 @@ until you regenerate. ### Removed +- **Java and Kotlin: the `metaobjects:docs` goal.** Documentation is generated the way code + is: the api reference is a `JavaApiDocsGenerator` or `KotlinApiDocsGenerator` `` + entry in the list `metaobjects:generate` runs, with its options in `` (see + **Added**), and nothing is written that `` does not declare. A pom that still + binds the goal fails with a line naming `mvn metaobjects:generate` and the migration + section. `generate` and `verify` refuse a pom that still sets the goal's parameters + (``, ``, ``, ``) instead of running and writing + no documentation. Ruling: ADR-0034 Amendment 9, which makes this the rule in all five ports + and numbers the release 1.1.0 (Maven 8.1.0) by the maintainer's explicit decision. + - **To upgrade**, replace the `docs` execution with one `` entry per language; + before and after `pom.xml`, and each parameter's new name, are in + [docs-are-generators.md, "Java and Kotlin"](docs/features/migrations/docs-are-generators.md#java-and-kotlin). + The page header's project label was the module's `artifactId`; set + `${project.artifactId}` to keep the pages byte for byte. +- **Java: `entity` no longer writes `Extractor` classes.** Through 8.0, + `JavaObjectCodeGenerator` wrote one beside each concrete class when the pom listed no + `extractor`: output no `` entry declared. Only `ExtractorCodeGenerator` writes + them now. + - **To upgrade**, if your code calls `Extractor` and your pom lists `entity` without + `extractor`: add an `ExtractorCodeGenerator` entry with the `entity` entry's `outputDir`, + naming args and `` + ([migration](docs/features/migrations/docs-are-generators.md#java-and-kotlin)). + - **The standalone `mermaid-er` generator (TypeScript).** `mermaidErDiagram()`, its `MermaidErOptions` type and the stable name `"mermaid-er"` are gone from `@metaobjectsdev/codegen-ts/generators`, the generator catalog and the cross-port @@ -1109,13 +1176,13 @@ until you regenerate. - Every Kotlin generator that types an enum now takes `providedEnumNamespace` / `providedEnumPackages`: the entity, Exposed table, Spring controller, relations and - output-parser generators, and the API pages `mvn metaobjects:docs` writes. Only the entity + output-parser generators, and `KotlinApiDocsGenerator`. Only the entity generator read them before, so for a `@provided` enum the data class named your class while the Exposed table and the controller named a class in the declaration's package that nothing generates, and the output did not compile. They now all resolve it through one function. A generator configured without the args fails at generate time for a model with a `@provided` enum, naming the enum, its package and both args. Set them once in the plugin's `` - and every generator, and the docs goal, reads the same values. + and every generator reads the same values. - **Upgrading an owned Kotlin generator.** A copy ejected before this release keeps compiling unchanged. The helper signatures it calls remain as deprecated forms: `KotlinTypeMapper.enumTypeName(field, entity)`, `KotlinEnumEmitter.emitEnumFile` without a diff --git a/README.md b/README.md index 6ddbb233a..411ba70bc 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ first-week wedge plan — and `meta init` picks up from there. |---|---|---|---| | TypeScript | **npm `1.0.13`** — the `@metaobjectsdev/*` packages | [`docs/ports/typescript.md`](docs/ports/typescript.md) | [`server/typescript/`](server/typescript/) · [`client/web/`](client/web/) | | Java | **Maven Central `8.0.13`** (`com.metaobjects:*` — the JVM major is npm major + 7) — loader + OMDB + render + Maven plugin all shipped; full conformance green | [`docs/ports/java.md`](docs/ports/java.md) | [`server/java/`](server/java/) | -| Kotlin | **Maven Central `8.0.13`** — codegen tier on top of Java: 15 generators (entity, Exposed table, names, relations, repository, output-parser, output-prompt, render-helper, extractor, filter-allowlist, validator, Spring config, storedProc, Spring controller, requirement-tests); 24 / 24 persistence-conformance | [`docs/ports/kotlin.md`](docs/ports/kotlin.md) | [`server/java/codegen-kotlin/`](server/java/codegen-kotlin/) · [`server/java/metadata-ktx/`](server/java/metadata-ktx/) | +| Kotlin | **Maven Central `8.0.13`** — codegen tier on top of Java: 16 generators (entity, Exposed table, names, relations, repository, output-parser, output-prompt, render-helper, extractor, filter-allowlist, validator, Spring config, storedProc, Spring controller, requirement-tests, api-docs); 24 / 24 persistence-conformance | [`docs/ports/kotlin.md`](docs/ports/kotlin.md) | [`server/java/codegen-kotlin/`](server/java/codegen-kotlin/) · [`server/java/metadata-ktx/`](server/java/metadata-ktx/) | | C# | **NuGet `1.0.13`** — loader + conformance + EF Core codegen + render engine + `dotnet meta` CLI all shipped | [`docs/ports/csharp.md`](docs/ports/csharp.md) | [`server/csharp/`](server/csharp/) | | Python | **PyPI `1.0.13`** — loader + conformance + render + entity-model codegen + ObjectManager runtime shipped; schema migrations are TS-owned (ADR-0015) | [`docs/ports/python.md`](docs/ports/python.md) | [`server/python/`](server/python/) | diff --git a/agent-context/servers/csharp.meta.json b/agent-context/servers/csharp.meta.json index d305d78a1..a41c5d26e 100644 --- a/agent-context/servers/csharp.meta.json +++ b/agent-context/servers/csharp.meta.json @@ -3,5 +3,7 @@ "install": "install the MetaObjects .NET tool (dotnet tool install) + add the MetaObjects.Codegen package", "codegenCommand": "dotnet meta gen", "docsCommand": "dotnet meta docs", + "docsCondition": "", + "docsMissing": "", "apiSubDir": "api/csharp" } diff --git a/agent-context/servers/java.meta.json b/agent-context/servers/java.meta.json index f2c3273f7..b0fffe246 100644 --- a/agent-context/servers/java.meta.json +++ b/agent-context/servers/java.meta.json @@ -2,6 +2,8 @@ "displayName": "Java", "install": "add com.metaobjects:metaobjects-metadata + metaobjects-codegen-spring + metaobjects-maven-plugin to your pom.xml", "codegenCommand": "mvn metaobjects:generate", - "docsCommand": "mvn metaobjects:docs", + "docsCommand": "mvn metaobjects:generate", + "docsCondition": " (when the project's generator list declares the api-docs generator)", + "docsMissing": "Declare `com.metaobjects.generator.apidocs.JavaApiDocsGenerator` as a `` entry in the pom's `` if it is missing", "apiSubDir": "api/java" } diff --git a/agent-context/servers/kotlin.meta.json b/agent-context/servers/kotlin.meta.json index e9dd7d930..72beb7ef8 100644 --- a/agent-context/servers/kotlin.meta.json +++ b/agent-context/servers/kotlin.meta.json @@ -2,6 +2,8 @@ "displayName": "Kotlin", "install": "add com.metaobjects:metaobjects-codegen-kotlin + metaobjects-metadata-ktx + metaobjects-maven-plugin to your pom.xml", "codegenCommand": "mvn metaobjects:generate", - "docsCommand": "mvn metaobjects:docs", + "docsCommand": "mvn metaobjects:generate", + "docsCondition": " (when the project's generator list declares the api-docs generator)", + "docsMissing": "Declare `com.metaobjects.generator.kotlin.apidocs.KotlinApiDocsGenerator` as a `` entry in the pom's `` if it is missing", "apiSubDir": "api/kotlin" } diff --git a/agent-context/servers/python.meta.json b/agent-context/servers/python.meta.json index dcfea618d..bfb1a8e27 100644 --- a/agent-context/servers/python.meta.json +++ b/agent-context/servers/python.meta.json @@ -3,5 +3,7 @@ "install": "pip install metaobjects", "codegenCommand": "metaobjects gen", "docsCommand": "metaobjects docs", + "docsCondition": "", + "docsMissing": "", "apiSubDir": "api/python" } diff --git a/agent-context/servers/typescript.meta.json b/agent-context/servers/typescript.meta.json index 38f5a718b..255274675 100644 --- a/agent-context/servers/typescript.meta.json +++ b/agent-context/servers/typescript.meta.json @@ -3,5 +3,7 @@ "install": "npm install -D @metaobjectsdev/cli @metaobjectsdev/codegen-ts", "codegenCommand": "npx meta gen", "docsCommand": "npx meta docs", + "docsCondition": "", + "docsMissing": "", "apiSubDir": "api" } diff --git a/agent-context/skills/metaobjects-codegen/references/java.md b/agent-context/skills/metaobjects-codegen/references/java.md index d8e1855ab..c02465c15 100644 --- a/agent-context/skills/metaobjects-codegen/references/java.md +++ b/agent-context/skills/metaobjects-codegen/references/java.md @@ -10,7 +10,7 @@ Maven plugin goal — there is no standalone `meta` binary on the Java side (the - Run - Write your own generator - When a generator's output is wrong — own the generator -- Docs — `mvn metaobjects:docs` +- Docs — the `api-docs` generator - `codegen-spring` generators - Discriminator inheritance (TPH) - Serializing generated objects @@ -138,16 +138,24 @@ repository. When a later MetaObjects release changes the reference generator, diff it against your copy and take what you want. Nothing in your build changes until you do. -## Docs — `mvn metaobjects:docs` +## Docs — the `api-docs` generator -A separate `docs` goal (`DocsMojo` — NOT a ``) emits this project's SDK api -surface (default `target/docs/api/java`), including `AGENT-API.md` — the exact imports, -signatures, and payload field shapes for the generated code. +The SDK api reference is a `` entry like any other, run by +`mvn metaobjects:generate`. It writes `AGENT-API.md` — the exact imports, signatures, and +payload field shapes for the generated code — plus a page per entity, under +`/api/java`. Nothing writes it unless the pom lists it; there is no docs goal +(removed in 8.1.0). -```bash -mvn metaobjects:docs # → target/docs/api/java (AGENT-API.md + per-entity pages) +```xml + + com.metaobjects.generator.apidocs.JavaApiDocsGenerator + ${project.build.directory}/docs + ``` +Optional ``: `apiSubDir` (default `api/java`), `layout` (`flat` or `package`), +`projectName`, `modelBaseUrl`. Give it an `outputDir` of generated files only. + **Before calling any generated code, read `api/java/AGENT-API.md`** — it carries the concrete imports and signatures so you don't have to guess them. @@ -170,8 +178,8 @@ separate `metaobjects-codegen-base` module instead.) | `LlmTraceHelperGenerator` | `TraceHelper.java` per concrete entity — the LLM-trace helper | | `SpringFilterAllowlistGenerator` | per-entity filter allowlist | | `SpringNamesGenerator` | `Names.java` — `public abstract class` of `static final String` names that MIRRORS THE METADATA TREE. Every node carries its own `TYPE`/`SUB_TYPE`/`NAME`, so `AuthorNames.NAME` is the OBJECT's name (`"Author"`), **not** a table name, and a physical name sits under the member that says what it is: `SOURCE__TABLE` / `_VIEW` / `_MATERIALIZED_VIEW` / `_PROC` / `_FUNCTION`, from the metamodel's own `@kind`-to-alias map, with `` being `PRIMARY` or `REPLICA` (a write-through entity has a member for each). Plus a `_FIELD`/`_COLUMN` pair per field and a complete `COLUMNS_BY_FIELD`; an `identity.secondary` or `index.lookup` also carries `IDENTITY__INDEX` / `INDEX__INDEX`, while `identity.primary` deliberately carries no index member (migrate names a PK by a dialect-conditional formula this artifact must not restate). **There is no `READ_ONLY`** — it was a derivation over `@kind`, never metadata, so ask `SOURCE__KIND`. Emitted for every object with a declared or inherited primary source, PLUS a fragment for any abstract base such an object extends (columns only, no source). A class whose object extends another one **extends** it (`class CopayAuthNames extends AuthNames`) rather than restating its constants — Java inherits static members, so `CopayAuthNames.SOURCE_PRIMARY_TABLE` and `CopayAuthNames.ID_COLUMN` both resolve through the base. **This port generates no SQL** (the repository is an interface you implement), so nothing generated consumes these — they exist for your implementation. | -| `JavaObjectCodeGenerator` | module `metaobjects-codegen-base` (`com.metaobjects.generator.direct.object.javacode`), a separate module from the Spring generators above. Flavor-selected via the `flavor` generator arg. `flavor=pojoAware` → `class extends PojoObject` (a concrete `MetaObjectAware` class with a `(MetaObject)` constructor) — its inherited `getMetaData()` back-reference is what breaks a default Jackson/Gson mapper, see "Serializing generated objects" below. `flavor=valueObject` → `class extends ValueObject` (map-backed; less hostile to a default mapper, but still not the sanctioned serialization path). Either concrete flavor also emits a self-registering `ObjectClassBindingProvider`, and a `Extractor` per concrete class unless `ExtractorCodeGenerator` is wired too. For a plain default-Jackson-friendly type, use the `codegen-spring` record surface instead — never `pojoAware`. | -| `ExtractorCodeGenerator` | also in `metaobjects-codegen-base`. One `Extractor` per concrete object, the same files `JavaObjectCodeGenerator` writes when this is not wired. Wire it as its own `` only to own it or to give it different args: same `outputDir`, `pkgPrefix` / `pkgSuffix` / `namePrefix` / `nameSuffix` and `` as the entity generator, which must run a concrete flavor in the same `` (an extractor for an object the entity generator wrote no class for does not compile). The plugin then stops the entity generator writing them. A pom with more than one entity generator entry needs one `ExtractorCodeGenerator` entry per entity entry, each with that entry's `outputDir`, naming args and ``: a single extractor generator in the run stops every entity entry writing its extractors. | +| `JavaObjectCodeGenerator` | module `metaobjects-codegen-base` (`com.metaobjects.generator.direct.object.javacode`), a separate module from the Spring generators above. Flavor-selected via the `flavor` generator arg. `flavor=pojoAware` → `class extends PojoObject` (a concrete `MetaObjectAware` class with a `(MetaObject)` constructor) — its inherited `getMetaData()` back-reference is what breaks a default Jackson/Gson mapper, see "Serializing generated objects" below. `flavor=valueObject` → `class extends ValueObject` (map-backed; less hostile to a default mapper, but still not the sanctioned serialization path). Either concrete flavor also emits a self-registering `ObjectClassBindingProvider`; it writes no extractors. For a plain default-Jackson-friendly type, use the `codegen-spring` record surface instead — never `pojoAware`. | +| `ExtractorCodeGenerator` | also in `metaobjects-codegen-base`. One `Extractor` per concrete object, and the only generator that writes them: list it or get none. Give it the same `outputDir`, `pkgPrefix` / `pkgSuffix` / `namePrefix` / `nameSuffix` and `` as the entity generator, which must run a concrete flavor in the same `` (an extractor for an object the entity generator wrote no class for does not compile). A pom with more than one entity generator entry needs one `ExtractorCodeGenerator` entry per entity entry, each with that entry's `outputDir`, naming args and ``. | **Owning one of these two.** `mvn metaobjects:eject -Dnames=entity,extractor -Dport=java` copies each generator into the `codegen/` module with the rest of its emit (`-Dport` is diff --git a/agent-context/skills/metaobjects-codegen/references/kotlin.md b/agent-context/skills/metaobjects-codegen/references/kotlin.md index 64b67df90..0f470d98a 100644 --- a/agent-context/skills/metaobjects-codegen/references/kotlin.md +++ b/agent-context/skills/metaobjects-codegen/references/kotlin.md @@ -136,17 +136,24 @@ repository. When a later MetaObjects release changes the reference generator, diff it against your copy and take what you want. Nothing in your build changes until you do. -## Docs — `mvn metaobjects:docs -Dmetaobjects.docs.language=kotlin` +## Docs — the `api-docs` generator -The shared `docs` goal (`DocsMojo`) renders the Kotlin SDK api surface via -`KotlinApiDocsRenderer` when pointed at the Kotlin language (default `target/docs/api/kotlin`), -including `AGENT-API.md` — the exact imports, signatures, and payload field shapes for the -generated code. +The Kotlin SDK api reference is a `` entry like any other, run by +`mvn metaobjects:generate`. It writes `AGENT-API.md` — the exact imports, signatures, and +payload field shapes for the generated code — plus a page per entity, under +`/api/kotlin`. Nothing writes it unless the pom lists it; there is no docs goal +(removed in 8.1.0). -```bash -mvn metaobjects:docs -Dmetaobjects.docs.language=kotlin # → target/docs/api/kotlin (AGENT-API.md + per-entity pages) +```xml + + com.metaobjects.generator.kotlin.apidocs.KotlinApiDocsGenerator + ${project.build.directory}/docs + ``` +Optional ``: `apiSubDir` (default `api/kotlin`), `layout` (`flat` or `package`), +`projectName`, `modelBaseUrl`. Give it an `outputDir` of generated files only. + **Before calling any generated code, read `api/kotlin/AGENT-API.md`.** ## `codegen-kotlin` generators diff --git a/agent-context/templates/always-on.md.mustache b/agent-context/templates/always-on.md.mustache index 69a23e79f..fd09ccbd0 100644 --- a/agent-context/templates/always-on.md.mustache +++ b/agent-context/templates/always-on.md.mustache @@ -29,7 +29,7 @@ inferring the answer from generated code, which is the disposable half. Not there? Run `meta docs`. It reads the metadata and the config and needs nothing else. {{/nodeDocsSurface}} {{^nodeDocsSurface}} -`{{docsCommand}}` writes ONE reference file under this project's docs output directory. It +`{{docsCommand}}` writes ONE reference file under this project's docs output directory{{docsCondition}}. It is generated from THIS project's metadata, so it describes what the project actually is rather than what the framework does in general — and reading it first is how you avoid inferring the answer from generated code, which is the disposable half. @@ -37,7 +37,7 @@ inferring the answer from generated code, which is the disposable half. - **`{{apiSubDir}}/AGENT-API.md`** — before calling generated code. The types, endpoints and filter operators the generators actually emitted. -Not there? Run `{{docsCommand}}`. +Not there? {{docsMissingAction}} `{{docsCommand}}`. The other three pages of that reference — `agent/schema.md` (persistence), `agent/ui.md` (forms and grids) and `agent/requirements.md` (what is already claimed, and what was diff --git a/docs/features/cli.md b/docs/features/cli.md index 806641525..55d5fae12 100644 --- a/docs/features/cli.md +++ b/docs/features/cli.md @@ -37,7 +37,7 @@ command surface splits in two: | **Canonical format** (`fmt`) | every port | `meta fmt` / `dotnet meta fmt` / `mvn metaobjects:fmt` / `metaobjects fmt` | (#304) ships in **every** port — the canonical serializer already exists in all five, so formatting is local, not Node-only. `--check` lists non-canonical files and exits non-zero without changing anything. Formats each file STANDALONE — own-mode, declared-here layer only (ADR-0039); an `extends` onto another file's base is preserved as-is, never resolved or erred on; a file declaring `overlay: true` anywhere — whether or not a same-file base exists — is reported as skipped rather than merged (merging would drop the overlay marker, a structural change fmt never makes). A YAML file is always skipped — no canonical YAML emitter exists (ADR-0006). Before writing, every port reloads the whole project with the candidate swapped in and refuses the write unless the reloaded model's canonical form is byte-identical to the untouched baseline — fmt never changes meaning. See [Fixture corpus](#meta-fmt--canonical-formatting-304) below and `fixtures/fmt-conformance/README.md` | | TS codegen | Node `meta` | `meta gen` | TS projects. **No `--template-spec` flag, deliberately** — `metaobjects.config.ts` already takes generator VALUES, so a declarative template generator is declared there (`templateGenerator()`, or `templateSpecToGenerators(parseTemplateSpec(spec))` to reuse a C#/Python spec file). Keeping it in the config is what lets `meta verify --codegen` regenerate WITH it, since that gate re-runs the config's generator list; see [declarative template scopes](codegen-concepts.md#declarative-template-scopes) | | C# codegen | `dotnet meta` | `dotnet meta gen` / `verify --templates` / `verify --codegen` | a .NET tool (`ToolCommandName=dotnet-meta`); invoked `dotnet meta` so it never shadows the Node `meta`; ships the ADR-0021 D2 subverbs (`--db` rejected, exit 2; bare `verify` = `--templates`). `gen` also accepts `--template-spec ` (+ `--template-root `, default `prompts/` when it exists, else `templates/`) — the declarative Mustache template-codegen surface (the cross-port JSON contract shared with Python), **auto-discovered at `/template-spec.json`** when the flag is absent. Prefer the conventional path: `verify --codegen` takes no `--template-spec`, so discovery is how the drift gate sees your template generators at all; see [declarative template scopes](codegen-concepts.md#declarative-template-scopes) | -| Java/Kotlin codegen | Maven plugin | `mvn metaobjects:generate` (`metaobjects:generate`) | Kotlin generators run through the same goal — see below. **No `--template-spec` flag, deliberately** — `` already loads a consumer class from the project classpath, so the declarative surface is `com.metaobjects.generator.template.TemplateScopeGenerator` wired as an ordinary `` with `