diff --git a/CHANGELOG.md b/CHANGELOG.md index 163624161..7e9e8f648 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -292,6 +292,13 @@ loading. A port that reports `1.2` does not know that vocabulary; upgrade every `docs/features/extending-with-providers.md` now has a worked example per language, and the `metaobjects-authoring` skill teaches it, with a reference file per language. +### Documentation + +- **Separate-repo model sharing (FR-023 Phase 2) close-out.** The feature page's Phase 2 section is now + the shipped per-port matrix (consume, check, publish, runtime load, transports), the deferred list + names what is still not built, and the verify, codegen, authoring, audit and capability-sheet skills + teach the Java, Kotlin and C# publish paths, the `deps` checks and the `maven` and `nuget` transports. + ### Changed - **`docsSiteFile()` builds the model explorer by default.** A project that lists diff --git a/agent-context/skills/metaobjects-audit/references/csharp.md b/agent-context/skills/metaobjects-audit/references/csharp.md index 0021f5894..3579d5371 100644 --- a/agent-context/skills/metaobjects-audit/references/csharp.md +++ b/agent-context/skills/metaobjects-audit/references/csharp.md @@ -42,8 +42,15 @@ dotnet meta gen metaobjects --out Generated --generators entity # narrow to de dotnet meta verify --codegen # regenerate to temp, diff vs committed output dotnet meta verify --templates # check {{field}} refs vs payload VO (bare default) +dotnet meta verify --deps # shared-model dependencies vs deps.lock.json (opt-in) ``` +`verify --deps` applies when the project declares `dependencies` in `.metaobjects/config.json`: it +hashes each `path` dependency against the lock and fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT` on +`drifted` or `unresolved` (a `maven`, `nuget`, `npm` or `python` dependency reports `unresolved`; +run the Node `meta deps check` for those). A project that publishes a model wires the +`SharedModelGenerator` in `codegen/Generators.cs`; `verify --codegen` drift-gates its output. + Schema migration + live-DB drift run through the **Node `meta` CLI** regardless of server language — see the migration reference. `dotnet meta verify --db` is rejected (exit 2). diff --git a/agent-context/skills/metaobjects-audit/references/java.md b/agent-context/skills/metaobjects-audit/references/java.md index fcd381860..9b5d4778b 100644 --- a/agent-context/skills/metaobjects-audit/references/java.md +++ b/agent-context/skills/metaobjects-audit/references/java.md @@ -40,6 +40,13 @@ mvn metaobjects:verify -Dmeta.verify.mode=codegen # regen to temp, diff vs c mvn metaobjects:verify -Dmeta.verify.mode=templates # {{field}} refs vs payload VO ``` +If the project declares `dependencies` in `.metaobjects/config.json` (a model shared from another +repository), also run `mvn metaobjects:verify -Dmeta.verify.mode=deps`: it hashes each `path` +dependency against `.metaobjects/deps.lock.json` and fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT` on +`drifted` or `unresolved` (a `maven`, `nuget`, `npm` or `python` dependency reports `unresolved`; +run the Node `meta deps check` for those). A project that publishes a model wires the +`shared-model` generator; `verify --codegen` drift-gates its output. + Schema migration + live-DB drift run through the **Node `meta` CLI** regardless of server language — see the migration reference. `mvn metaobjects:verify -Dmeta.verify.mode=db` is rejected (exit 2). diff --git a/agent-context/skills/metaobjects-audit/references/kotlin.md b/agent-context/skills/metaobjects-audit/references/kotlin.md index 1928e3687..586fdaa6e 100644 --- a/agent-context/skills/metaobjects-audit/references/kotlin.md +++ b/agent-context/skills/metaobjects-audit/references/kotlin.md @@ -44,6 +44,13 @@ mvn metaobjects:verify -Dmeta.verify.mode=codegen # regen to temp, diff vs c mvn metaobjects:verify -Dmeta.verify.mode=templates # {{field}} refs vs payload VO ``` +If the project declares `dependencies` in `.metaobjects/config.json` (a model shared from another +repository), also run `mvn metaobjects:verify -Dmeta.verify.mode=deps`: it hashes each `path` +dependency against `.metaobjects/deps.lock.json` and fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT` on +`drifted` or `unresolved` (a `maven`, `nuget`, `npm` or `python` dependency reports `unresolved`; +run the Node `meta deps check` for those). A project that publishes a model wires the +`shared-model` generator; `verify --codegen` drift-gates its output. + Kotlin generators run through the **same Maven plugin goal** as Java generators — both are SPI-discovered by the `metaobjects-maven-plugin`. Schema migration + live-DB drift run through the **Node `meta` CLI** regardless of server language — see the diff --git a/agent-context/skills/metaobjects-audit/references/python.md b/agent-context/skills/metaobjects-audit/references/python.md index 47beec1af..92c1d4250 100644 --- a/agent-context/skills/metaobjects-audit/references/python.md +++ b/agent-context/skills/metaobjects-audit/references/python.md @@ -40,8 +40,14 @@ metaobjects gen # run every target's generators (metaobjec metaobjects gen --generators entity # narrow to declared entries metaobjects verify --codegen # regenerate to temp, diff vs each committed outDir (bare default) metaobjects verify --templates # {{field}} refs vs payload VO +metaobjects deps check # shared-model dependencies vs deps.lock.json (also: verify --deps) ``` +`deps check` applies when the project declares `dependencies` in `.metaobjects/config.json`: it +hashes each `path` dependency against the lock and fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT` on +`drifted` or `unresolved` (a `maven`, `nuget`, `npm` or `python` dependency reports `unresolved`; +run the Node `meta deps check` for those). Python consumes a shared model but cannot publish one. + With no `metaobjects.config.yaml`, `gen` exits 2 and generates nothing. A target's `generators` takes stable generator names: `entity`, `routes`, `filter-allowlist`, `names`, `output-parser`, `extractor`, `output-prompt`, `render-helper`, `trace-helper`, diff --git a/agent-context/skills/metaobjects-authoring/references/metadata-dependencies.md b/agent-context/skills/metaobjects-authoring/references/metadata-dependencies.md index 2574655ff..35ac24804 100644 --- a/agent-context/skills/metaobjects-authoring/references/metadata-dependencies.md +++ b/agent-context/skills/metaobjects-authoring/references/metadata-dependencies.md @@ -9,10 +9,14 @@ committed snapshot — that snapshot loads BEFORE your own files, so a foreign abstract resolves via `extends` and a foreign node re-opens via `overlay: true` exactly like a local one. A dependency names one transport: `path` (a directory relative to the directory holding `.metaobjects/`), `npm` (an installed npm -package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`) -or `python` (an installed Python package by its import name, e.g. -`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`). For -`npm`/`python`, install the package with the project's package manager first; +package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`), +`python` (an installed Python package by its import name, e.g. +`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`), `maven` +(`{ "name": "acme-model", "maven": "com.acme:acme-model", "version": "1.0.0" }`, a JAR in the +local Maven repository) or `nuget` +(`{ "name": "acme-model", "nuget": "Acme.Model", "version": "1.0.0" }`, a package in the NuGet +global packages folder). For +`npm`/`python`/`maven`/`nuget`, install or restore the package with the project's package manager first; `meta deps sync` locates it, copies its shared model into the snapshot, and says what to install when it is missing. Prefer the package transport over a `path` into someone else's checkout when the publisher releases a package. Two rules are diff --git a/agent-context/skills/metaobjects-codegen/references/dependencies-and-shared-models.md b/agent-context/skills/metaobjects-codegen/references/dependencies-and-shared-models.md index 3d0cdc883..89050885d 100644 --- a/agent-context/skills/metaobjects-codegen/references/dependencies-and-shared-models.md +++ b/agent-context/skills/metaobjects-codegen/references/dependencies-and-shared-models.md @@ -41,10 +41,19 @@ replace those calls: an unmodified copy publishes the same bytes as the packaged generator. To publish through a package, point its `target` inside the package (an npm package's directory listed in `files`; a Python package's directory shipped as package data), run `meta gen`, then release the package as usual; consumers -declare an `npm` or `python` dependency on it. With no `version` option the +declare an `npm`, `python`, `maven` or `nuget` dependency on it. With no `version` option the manifest takes the nearest `package.json` version, else a `pyproject.toml` `[project]` version — pass `version` when neither is the package consumers install. -Only TypeScript can run it in Phase 1a. TypeScript, Python, Java, Kotlin (through -Java's loader and Maven plugin) and C# can *consume* a dependency, and only the -TypeScript toolchain can *publish* one. +TypeScript, Java, Kotlin and C# can *publish* with byte-identical output: the Java and Kotlin +`shared-model` generator runs through `mvn metaobjects:generate` (`SharedModelGenerator` / +`KotlinSharedModelGenerator`, args `name`, `include`, `exclude`, `files`, `version`; the version +defaults to the module ``); the C# one is `new SharedModelGenerator { ModelName, Include, +Files, OutDir }` in `codegen/Generators.cs` through `dotnet meta gen` (version from the project +``). Eject with `mvn metaobjects:eject -Dnames=shared-model -Dport=java|kotlin` or `dotnet +meta eject shared-model`. A JVM publisher ships the pair as the JAR's `metaobjects/` resources and a +C# publisher as the NuGet package's `metaobjects/` content; consumers declare +`{ "name": "x", "maven": "com.acme:model", "version": "1.0.0" }` or +`{ "name": "x", "nuget": "Acme.Model", "version": "1.0.0" }` (also `npm`/`python`/`path`). +TypeScript, Python, Java, Kotlin and C# *consume*; Python cannot publish. Node `meta deps sync` +remains the only writer of the lock and snapshot in every port. Full detail: `docs/features/metadata-dependencies.md`. diff --git a/agent-context/skills/metaobjects-fit-assessment/references/capability-sheet.md b/agent-context/skills/metaobjects-fit-assessment/references/capability-sheet.md index d18d8a70c..db42e0539 100644 --- a/agent-context/skills/metaobjects-fit-assessment/references/capability-sheet.md +++ b/agent-context/skills/metaobjects-fit-assessment/references/capability-sheet.md @@ -36,15 +36,18 @@ building block. Every generator is a reference helper an adopter selects, ejects - **Sharing a model** (`docs/features/metadata-dependencies.md`): in one repository, every port reads the same metadata directory (`sources`), so a TS service and a Java, C# or Python service can generate from one declaration today. **Across repositories**, a published model - with a hash-locked snapshot works for **TypeScript publishers only**; **TypeScript, Python, - Java, Kotlin and C# consume** it at build time (a committed `.metaobjects/deps/` snapshot loaded - ahead of the project's own files; `extends`/overlay onto a dependency's node resolves; imported - nodes are not generated unless `scope.include` names their package). The Node `meta deps sync` - is the only writer of the lock and snapshot, so a Java, Kotlin or C# consumer needs Node to - sync. Dependencies come from a `path`, an npm package or a Python package; the Maven and NuGet - transports are design only. Java, Kotlin, Python and C# cannot publish; the Spring runtime does - not yet auto-load the snapshot, and the Java/Kotlin `verify` does not yet check dependency - drift. Plain vendoring (`docs/features/metadata-sources.md`, "Vendoring") still works and + with a hash-locked snapshot works in every port: **TypeScript, Java, Kotlin and C# publish** it + (`sharedModelFile()`, or the `shared-model` generator through `metaobjects:generate` and + `dotnet meta gen`, all ejectable); **TypeScript, Python, Java, Kotlin and C# consume** it at + build time (a committed `.metaobjects/deps/` snapshot loaded ahead of the project's own files; + `extends`/overlay onto a dependency's node resolves; imported nodes are not generated unless + `scope.include` names their package), and the Spring runtime auto-loads the snapshot. Every port + can check drift (`meta deps check`, `metaobjects deps check`, `mvn metaobjects:verify + -Dmeta.verify.mode=deps`, `dotnet meta verify --deps`). The Node `meta deps sync` is the only + writer of the lock and snapshot, so a Java, Kotlin, C# or Python consumer needs Node to sync. + Dependencies come from a `path`, an npm or Python package, a Maven artifact (a JAR in the local + repository) or a NuGet package; only Node resolves the package transports in `check`. Python + cannot publish, and a JVM classpath read with no committed snapshot is not built. Plain vendoring (`docs/features/metadata-sources.md`, "Vendoring") still works and carries no upstream hash check. Source: `docs/features/metadata-dependencies.md`, "Phase 2". - **Libraries** (`docs/features/libraries.md`): `iam` (preview) and `ai` (stable) ship as declared designs; the core layer is sourceless and adds no tables. Mention one only when the diff --git a/agent-context/skills/metaobjects-verify/SKILL.md b/agent-context/skills/metaobjects-verify/SKILL.md index 54ffb4673..57b556e1f 100644 --- a/agent-context/skills/metaobjects-verify/SKILL.md +++ b/agent-context/skills/metaobjects-verify/SKILL.md @@ -166,15 +166,14 @@ with `ERR_DEPENDENCY_SNAPSHOT_STALE` naming the fix: run `meta deps sync`. if any reference isn't on the payload VO. This is the build-time gate for the prompt-construction pillar. -- **`--deps`** — dependency drift (FR-023, **Node `meta` only** — but **any - backend**, like `--db`: the check reads only `.metaobjects/config.json` and has - no backend dependency of its own). Re-resolves each declared dependency's `path` +- **`--deps`** — dependency drift (FR-023). Re-resolves each declared dependency right now and compares its installed artifact's hash against - `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Only - TypeScript and Python additionally LOAD the resulting snapshot and honour the - default-exclusion it implies — a Java/Kotlin/C# project can run this gate today - even though its own codegen can't yet consume a dependency. Never part of the - bare-`verify` default: it + `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Node + `meta` resolves every transport (`path`, `npm`, `python`, `maven`, `nuget`); the + Python, Java/Kotlin and C# checks resolve `path` only and report any other + transport `unresolved`, naming Node `meta deps check` (a check that cannot check + must not pass). Every port also loads the committed snapshot and honours the + default-exclusion it implies. Never part of the bare-`verify` default: it needs the publisher's `path` reachable, which CI checking out only your own repo may not have. Reports `current` / `drifted` / `unresolved` per dependency; `drifted` or `unresolved` fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT`, fix is @@ -188,7 +187,16 @@ port's own build tool, not the Node `meta`: | TS | `meta verify --codegen` | `meta verify --templates` | `meta verify --db ` | | Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=codegen` | `mvn metaobjects:verify -Dmeta.verify.mode=templates` | Node `meta verify --db` only | | C# | `dotnet meta verify --codegen` | `dotnet meta verify --templates` | Node `meta verify --db` only | -| Python | `metaobjects verify --codegen` | `metaobjects verify --templates` | Node `meta verify --db` only | +| Python | `metaobjects verify` (`--codegen` is in the default) | n/a | Node `meta verify --db` only | + +Dependency drift (`--deps`) per port: + +| Port | Dependency drift | +|---|---| +| TS | `meta deps check`, `meta verify --deps` | +| Python | `metaobjects deps check`, `metaobjects verify --deps` | +| Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=deps` | +| C# | `dotnet meta verify --deps` | Every non-TS port's `verify` rejects `--db` outright (exit 2, "schema verify is the migrate engine") — schema drift always runs through the Node `meta verify --db`, diff --git a/docs/CONFORMANCE.md b/docs/CONFORMANCE.md index 599477efb..28981161f 100644 --- a/docs/CONFORMANCE.md +++ b/docs/CONFORMANCE.md @@ -485,7 +485,7 @@ above: one committed `cases.json`, no per-port fixture, no ledger. The corpus ha Kotlin runs the same goal), by **Python**, in `tests/conformance/test_dependency_conformance.py` (`metaobjects deps check` and `verify --deps`), and by **C#**, in `DependencyConformanceTests` (`dotnet meta verify --deps`). The arm exists so that each port's check is written against the - same edge cases (Phase 2, #482). + same edge cases (FR-023 Phase 2, #482, shipped). - **Transport (32 cases, `transport-cases.json`).** The `npm`, `python`, `maven` and `nuget` transports `meta deps sync` uses to find an installed package: npm packages under a temp `node_modules`, Python packages on a temp import path, jars in a temp local Maven repository, packages in a temp NuGet cache, diff --git a/docs/features/metadata-dependencies.md b/docs/features/metadata-dependencies.md index aa04b892a..d188c5bf0 100644 --- a/docs/features/metadata-dependencies.md +++ b/docs/features/metadata-dependencies.md @@ -685,38 +685,50 @@ manager. What's different: the artifact is **one flattened, generated file** rat than a directory of hand-placed sources, its manifest is generated rather than hand-written, and `meta deps sync` copies it into a **committed snapshot** rather than reading it live off the classpath at build time — the classpath-at-build-time -read is recorded as a Phase 2 JVM option, not gone, but the committed snapshot is the -cross-port contract every consumer gets today. - -## Phase 2: Java, Kotlin and C# - -Tracked in [#482](https://github.com/metaobjectsdev/metaobjects/issues/482). Today TypeScript, -Python, Java, Kotlin and C# consume a dependency (Java and Kotlin shipped in slice S3, C# in S6). -A port that does not read the lock fails loudly on a model that references a node a dependency -would supply (`ERR_UNRESOLVED_OBJECT_REF`), never silently. Phase 2 adds no new contract. The manifest, the -lock, the committed snapshot and the 28-case resolution corpus are plain files that every port -already has the pieces to read; what is missing is each port *loading* the snapshot. +read with no committed snapshot (`"commit": false`) is [deferred](#deferred), and the committed snapshot is the +cross-port contract every consumer gets. + +## Phase 2: Java, Kotlin and C# (shipped) + +Phase 2 ([#482](https://github.com/metaobjectsdev/metaobjects/issues/482)) is built. It added no new +contract: the manifest, the lock, the committed snapshot and the resolution corpus are plain files +every port reads. What it added is each port *loading* the snapshot, *checking* it, and (for Java, +Kotlin and C#) *publishing* one. A port that does not read the lock still fails loudly on a model +that references a node a dependency would supply (`ERR_UNRESOLVED_OBJECT_REF`), never silently. + +| | TypeScript | Python | Java | Kotlin | C# | +|---|---|---|---|---|---| +| **Consume** (load the snapshot, scope, extend, overlay) | ✓ | ✓ | ✓ every rung of the Maven plugin's source ladder | ✓ through Java's loader and plugin | ✓ every rung of `dotnet meta`'s source ladder | +| **Runtime load** | Node reads it | n/a (build-time) | ✓ Spring loads `.metaobjects/deps.lock.json` and `deps/**` from the classpath | ✓ same | n/a (build-time) | +| **Check** | `meta deps check`, `meta verify --deps` | `metaobjects deps check`, `verify --deps` | `mvn metaobjects:verify -Dmeta.verify.mode=deps` | same goal | `dotnet meta verify --deps` | +| **Publish** (`shared-model`, ejectable) | `sharedModelFile()` | no | ✓ `SharedModelGenerator` via `metaobjects:generate` | ✓ `KotlinSharedModelGenerator` | ✓ `SharedModelGenerator` via `dotnet meta gen` | +| **Transports `sync` reads** | `path`, `npm`, `python`, `maven`, `nuget` (Node `meta deps sync` is the only writer, for every port) | | | | | +| **Transports `check` resolves** | all five | `path` | `path` | `path` | `path` | + +Publishers in all three ports write the same artifact and manifest bytes as `sharedModelFile()`, +gated by `fixtures/shared-model-conformance/`. See the port pages: [Java](../ports/java.md#consuming-a-shared-model-dependencies), +[Kotlin](../ports/kotlin.md), [C#](../ports/csharp.md#publishing-a-shared-model-shared-model). Two rulings shape it: - **Node `meta deps sync` stays the only writer of the lock and the snapshot.** The other ports - load and check; a Java or C# project needs Node to sync, as a schema-owning project already + load, check and publish; a Java or C# project needs Node to sync, as a schema-owning project already needs it for `meta migrate`. Because the lock is then written by one tool, its byte format never becomes a cross-port contract. - **The Java Spring runtime loads the snapshot automatically** when `.metaobjects/deps.lock.json` is on the classpath, so a Spring app whose entity `extends` a dependency's node does not fail at boot for want of one line of configuration. -**Java and Kotlin: runtime load and `verify` (shipped, S4 and S5).** A Spring app loads the committed -snapshot at runtime: `metaobjects:generate` ships `.metaobjects/deps.lock.json` and -`.metaobjects/deps/**` on the classpath, and the application loader reads them when the lock is -there, with the build-time scoping and error codes. `mvn metaobjects:verify -Dmeta.verify.mode=deps` -is the Java and Kotlin `meta deps check`: it resolves a `path` dependency, hashes its artifact against -the lock and fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT` on `drifted` or `unresolved`. It is opt-in, and -an `npm`, `python`, `maven` or `nuget` dependency is `unresolved` there (run the Node `meta deps check` for those). See +**Java and Kotlin: runtime load and `verify`.** `metaobjects:generate` ships +`.metaobjects/deps.lock.json` and `.metaobjects/deps/**` on the classpath, and the application loader +reads them when the lock is there, with the build-time scoping and error codes. +`mvn metaobjects:verify -Dmeta.verify.mode=deps` is the Java and Kotlin `meta deps check`: it +resolves a `path` dependency, hashes its artifact against the lock and fails with +`ERR_DEPENDENCY_UPSTREAM_DRIFT` on `drifted` or `unresolved`. It is opt-in, and an `npm`, `python`, +`maven` or `nuget` dependency is `unresolved` there (run the Node `meta deps check` for those). See [the Java port page](../ports/java.md#consuming-a-shared-model-dependencies). -**`meta deps sync` and `check` on a Maven- or C#-shaped project (shipped).** Both commands read +**`meta deps sync` and `check` on a Maven- or C#-shaped project.** Both commands read only `.metaobjects/config.json`, and finish with a proof that the dependency set loads. A project whose own metadata is in a build-tool directory (`src/main/resources/metadata`, a C# project's metadata directory) declares no neutral `sources`, and a project may use vocabulary only its own @@ -729,19 +741,19 @@ same path, which is why the fallback is announced. A load that also has any othe an unresolved `extends` onto a removed dependency node, still fails the command and, for `sync`, rolls the lock and snapshot back. -**Packaged transports: Maven and NuGet (shipped).** The `path` transport needs the +**Packaged transports: Maven and NuGet.** The `path` transport needs the publisher's directory on disk. A JVM or .NET consumer that cannot reach it resolves a published model from the package manager's own store instead: a Maven artifact (a JAR in the local repository) or a NuGet package (in the global packages folder), each carrying the same -`metaobjects.pkg.json` and artifact pair that `sharedModelFile()` writes (see -[the transports](#declaring-a-dependency) above). Per the single-writer ruling it is Node `meta +`metaobjects.pkg.json` and artifact pair that a publisher writes (see +[the transports](#declaring-a-dependency) above). A publisher ships the pair inside its JAR (as +`metaobjects/` resources) or its NuGet package (as `metaobjects/` content), declared as +`{ "name": "x", "maven": "com.acme:acme-model", "version": "1.0.0" }` or +`{ "name": "x", "nuget": "Acme.Model", "version": "1.0.0" }`. Per the single-writer ruling it is Node `meta deps sync` that reads the pair out of the JAR or the package and writes the same snapshot and lock entry a `path` sync writes, so everything downstream (`check`, load, scope, the corpus) is -unchanged; nothing in a port's own build resolves a dependency, and the Java, Python and C# -`check` report a `maven` or `nuget` dependency `unresolved` and name the Node `meta deps check`, -as they do for `npm` and `python`. This generalizes the resources-JAR pattern described above. A -JVM *classpath read with no committed snapshot* (the legacy behaviour) stays a separate, deferred -option. +unchanged; nothing in a port's own build resolves a dependency. This generalizes the resources-JAR +pattern described above. ## Deferred @@ -762,7 +774,10 @@ but **not** built yet — do not assume any of the following exists: - **A runtime `ObjectManager` scope predicate.** Nothing at runtime refuses to serve an imported entity — "what's imported" is a load-time/codegen concept today, not a runtime one. -- **Python as a publisher** — Java, Kotlin and C# publish (S8 and S9); Python consumes only. +- **Python as a publisher** — Java, Kotlin and C# publish; Python consumes only. +- **A JVM classpath read with `"commit": false`** — a Java or Kotlin build reading a dependency's + artifact straight off the classpath with no committed snapshot. The committed snapshot is the only + shipped path. - **`npm`, `python`, `maven` and `nuget` transports in the Python, Java and C# check.** Those ports' check resolves `path` only; any other dependency reports `unresolved` and names the Node `meta deps check`, because resolving it needs the consumer's installed packages or local package @@ -795,8 +810,8 @@ but **not** built yet — do not assume any of the following exists: - [`fixtures/shared-model-conformance/`](../../fixtures/shared-model-conformance/) — 11 cases pinning what a publisher writes: the exact artifact and manifest bytes for a source tree and `include` / `exclude` / `files`, and the refusals (an empty selection, a closure failure naming - every `referrer → target` pair, vocabulary a consumer's toolchain does not ship). TypeScript runs - all of it; Python runs the serializer arm. + every `referrer → target` pair, vocabulary a consumer's toolchain does not ship). TypeScript, Java + (Kotlin through the same engine) and C# run all of it; Python runs the serializer arm. ## See also diff --git a/docs/ports/csharp.md b/docs/ports/csharp.md index dc01f83ab..ec8063989 100644 --- a/docs/ports/csharp.md +++ b/docs/ports/csharp.md @@ -125,7 +125,7 @@ manifest, a hash that does not match, or no lock entry yet) are the same states `ERR_DEPENDENCY_UPSTREAM_DRIFT` exit as `meta deps check`. The check runs before the metadata loads, so a dependency not yet synced is reported `unresolved` first; the load that follows still refuses the missing or stale snapshot with `ERR_DEPENDENCY_SNAPSHOT_STALE` and exit 2. It never writes anything, it is never -part of a bare `verify`, and an `npm` or `python` dependency is reported `unresolved` (run the Node +part of a bare `verify`, and an `npm`, `python`, `maven` or `nuget` dependency is reported `unresolved` (run the Node `meta deps check` for those). ### Custom providers (optional) diff --git a/docs/ports/java.md b/docs/ports/java.md index c168e6ff6..d01f74779 100644 --- a/docs/ports/java.md +++ b/docs/ports/java.md @@ -221,7 +221,7 @@ fails boot. If the lock is absent and nothing is declared, nothing changes. re-resolves each declared dependency's `path`, reads the publisher's `metaobjects.pkg.json`, hashes the artifact and reports `current`, `drifted` or `unresolved` per dependency; the last two fail the build with `ERR_DEPENDENCY_UPSTREAM_DRIFT`. It loads no model, writes nothing, and is not part of the default -gate set because it needs the publisher reachable. An `npm` or `python` dependency is found by the Node +gate set because it needs the publisher reachable. An `npm`, `python`, `maven` or `nuget` dependency is found by the Node tool, so it reports `unresolved` here: run `meta deps check` for it. ### Custom providers (optional) diff --git a/docs/ports/python.md b/docs/ports/python.md index 39af4b6f8..82409c66c 100644 --- a/docs/ports/python.md +++ b/docs/ports/python.md @@ -161,7 +161,7 @@ Each dependency is `current`, `drifted` or `unresolved` (no directory, a bad man does not match, or no lock entry yet); anything but `current` exits 1 with `ERR_DEPENDENCY_UPSTREAM_DRIFT`, and a lock that cannot be read exits 2. `deps check` also loads the locked snapshots together once the hashes match. Neither writes anything, `--deps` is never -part of a bare `verify`, and an `npm` or `python` dependency reports `unresolved` (run the Node +part of a bare `verify`, and an `npm`, `python`, `maven` or `nuget` dependency reports `unresolved` (run the Node `meta deps check` for those). See [Metadata dependencies](../features/metadata-dependencies.md). `verify --codegen` regenerates exactly the list `gen` runs and compares, so the two can diff --git a/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-audit/references/java.md b/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-audit/references/java.md index fcd381860..9b5d4778b 100644 --- a/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-audit/references/java.md +++ b/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-audit/references/java.md @@ -40,6 +40,13 @@ mvn metaobjects:verify -Dmeta.verify.mode=codegen # regen to temp, diff vs c mvn metaobjects:verify -Dmeta.verify.mode=templates # {{field}} refs vs payload VO ``` +If the project declares `dependencies` in `.metaobjects/config.json` (a model shared from another +repository), also run `mvn metaobjects:verify -Dmeta.verify.mode=deps`: it hashes each `path` +dependency against `.metaobjects/deps.lock.json` and fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT` on +`drifted` or `unresolved` (a `maven`, `nuget`, `npm` or `python` dependency reports `unresolved`; +run the Node `meta deps check` for those). A project that publishes a model wires the +`shared-model` generator; `verify --codegen` drift-gates its output. + Schema migration + live-DB drift run through the **Node `meta` CLI** regardless of server language — see the migration reference. `mvn metaobjects:verify -Dmeta.verify.mode=db` is rejected (exit 2). diff --git a/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-audit/references/kotlin.md b/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-audit/references/kotlin.md index 1928e3687..586fdaa6e 100644 --- a/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-audit/references/kotlin.md +++ b/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-audit/references/kotlin.md @@ -44,6 +44,13 @@ mvn metaobjects:verify -Dmeta.verify.mode=codegen # regen to temp, diff vs c mvn metaobjects:verify -Dmeta.verify.mode=templates # {{field}} refs vs payload VO ``` +If the project declares `dependencies` in `.metaobjects/config.json` (a model shared from another +repository), also run `mvn metaobjects:verify -Dmeta.verify.mode=deps`: it hashes each `path` +dependency against `.metaobjects/deps.lock.json` and fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT` on +`drifted` or `unresolved` (a `maven`, `nuget`, `npm` or `python` dependency reports `unresolved`; +run the Node `meta deps check` for those). A project that publishes a model wires the +`shared-model` generator; `verify --codegen` drift-gates its output. + Kotlin generators run through the **same Maven plugin goal** as Java generators — both are SPI-discovered by the `metaobjects-maven-plugin`. Schema migration + live-DB drift run through the **Node `meta` CLI** regardless of server language — see the diff --git a/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md b/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md index 2574655ff..35ac24804 100644 --- a/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md +++ b/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md @@ -9,10 +9,14 @@ committed snapshot — that snapshot loads BEFORE your own files, so a foreign abstract resolves via `extends` and a foreign node re-opens via `overlay: true` exactly like a local one. A dependency names one transport: `path` (a directory relative to the directory holding `.metaobjects/`), `npm` (an installed npm -package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`) -or `python` (an installed Python package by its import name, e.g. -`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`). For -`npm`/`python`, install the package with the project's package manager first; +package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`), +`python` (an installed Python package by its import name, e.g. +`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`), `maven` +(`{ "name": "acme-model", "maven": "com.acme:acme-model", "version": "1.0.0" }`, a JAR in the +local Maven repository) or `nuget` +(`{ "name": "acme-model", "nuget": "Acme.Model", "version": "1.0.0" }`, a package in the NuGet +global packages folder). For +`npm`/`python`/`maven`/`nuget`, install or restore the package with the project's package manager first; `meta deps sync` locates it, copies its shared model into the snapshot, and says what to install when it is missing. Prefer the package transport over a `path` into someone else's checkout when the publisher releases a package. Two rules are diff --git a/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md b/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md index 3d0cdc883..89050885d 100644 --- a/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md +++ b/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md @@ -41,10 +41,19 @@ replace those calls: an unmodified copy publishes the same bytes as the packaged generator. To publish through a package, point its `target` inside the package (an npm package's directory listed in `files`; a Python package's directory shipped as package data), run `meta gen`, then release the package as usual; consumers -declare an `npm` or `python` dependency on it. With no `version` option the +declare an `npm`, `python`, `maven` or `nuget` dependency on it. With no `version` option the manifest takes the nearest `package.json` version, else a `pyproject.toml` `[project]` version — pass `version` when neither is the package consumers install. -Only TypeScript can run it in Phase 1a. TypeScript, Python, Java, Kotlin (through -Java's loader and Maven plugin) and C# can *consume* a dependency, and only the -TypeScript toolchain can *publish* one. +TypeScript, Java, Kotlin and C# can *publish* with byte-identical output: the Java and Kotlin +`shared-model` generator runs through `mvn metaobjects:generate` (`SharedModelGenerator` / +`KotlinSharedModelGenerator`, args `name`, `include`, `exclude`, `files`, `version`; the version +defaults to the module ``); the C# one is `new SharedModelGenerator { ModelName, Include, +Files, OutDir }` in `codegen/Generators.cs` through `dotnet meta gen` (version from the project +``). Eject with `mvn metaobjects:eject -Dnames=shared-model -Dport=java|kotlin` or `dotnet +meta eject shared-model`. A JVM publisher ships the pair as the JAR's `metaobjects/` resources and a +C# publisher as the NuGet package's `metaobjects/` content; consumers declare +`{ "name": "x", "maven": "com.acme:model", "version": "1.0.0" }` or +`{ "name": "x", "nuget": "Acme.Model", "version": "1.0.0" }` (also `npm`/`python`/`path`). +TypeScript, Python, Java, Kotlin and C# *consume*; Python cannot publish. Node `meta deps sync` +remains the only writer of the lock and snapshot in every port. Full detail: `docs/features/metadata-dependencies.md`. diff --git a/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-verify/SKILL.md b/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-verify/SKILL.md index 54ffb4673..57b556e1f 100644 --- a/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-verify/SKILL.md +++ b/fixtures/agent-context-conformance/java-kotlin-react-tanstack/expected/.claude/skills/metaobjects-verify/SKILL.md @@ -166,15 +166,14 @@ with `ERR_DEPENDENCY_SNAPSHOT_STALE` naming the fix: run `meta deps sync`. if any reference isn't on the payload VO. This is the build-time gate for the prompt-construction pillar. -- **`--deps`** — dependency drift (FR-023, **Node `meta` only** — but **any - backend**, like `--db`: the check reads only `.metaobjects/config.json` and has - no backend dependency of its own). Re-resolves each declared dependency's `path` +- **`--deps`** — dependency drift (FR-023). Re-resolves each declared dependency right now and compares its installed artifact's hash against - `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Only - TypeScript and Python additionally LOAD the resulting snapshot and honour the - default-exclusion it implies — a Java/Kotlin/C# project can run this gate today - even though its own codegen can't yet consume a dependency. Never part of the - bare-`verify` default: it + `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Node + `meta` resolves every transport (`path`, `npm`, `python`, `maven`, `nuget`); the + Python, Java/Kotlin and C# checks resolve `path` only and report any other + transport `unresolved`, naming Node `meta deps check` (a check that cannot check + must not pass). Every port also loads the committed snapshot and honours the + default-exclusion it implies. Never part of the bare-`verify` default: it needs the publisher's `path` reachable, which CI checking out only your own repo may not have. Reports `current` / `drifted` / `unresolved` per dependency; `drifted` or `unresolved` fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT`, fix is @@ -188,7 +187,16 @@ port's own build tool, not the Node `meta`: | TS | `meta verify --codegen` | `meta verify --templates` | `meta verify --db ` | | Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=codegen` | `mvn metaobjects:verify -Dmeta.verify.mode=templates` | Node `meta verify --db` only | | C# | `dotnet meta verify --codegen` | `dotnet meta verify --templates` | Node `meta verify --db` only | -| Python | `metaobjects verify --codegen` | `metaobjects verify --templates` | Node `meta verify --db` only | +| Python | `metaobjects verify` (`--codegen` is in the default) | n/a | Node `meta verify --db` only | + +Dependency drift (`--deps`) per port: + +| Port | Dependency drift | +|---|---| +| TS | `meta deps check`, `meta verify --deps` | +| Python | `metaobjects deps check`, `metaobjects verify --deps` | +| Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=deps` | +| C# | `dotnet meta verify --deps` | Every non-TS port's `verify` rejects `--db` outright (exit 2, "schema verify is the migrate engine") — schema drift always runs through the Node `meta verify --db`, diff --git a/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-audit/references/java.md b/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-audit/references/java.md index fcd381860..9b5d4778b 100644 --- a/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-audit/references/java.md +++ b/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-audit/references/java.md @@ -40,6 +40,13 @@ mvn metaobjects:verify -Dmeta.verify.mode=codegen # regen to temp, diff vs c mvn metaobjects:verify -Dmeta.verify.mode=templates # {{field}} refs vs payload VO ``` +If the project declares `dependencies` in `.metaobjects/config.json` (a model shared from another +repository), also run `mvn metaobjects:verify -Dmeta.verify.mode=deps`: it hashes each `path` +dependency against `.metaobjects/deps.lock.json` and fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT` on +`drifted` or `unresolved` (a `maven`, `nuget`, `npm` or `python` dependency reports `unresolved`; +run the Node `meta deps check` for those). A project that publishes a model wires the +`shared-model` generator; `verify --codegen` drift-gates its output. + Schema migration + live-DB drift run through the **Node `meta` CLI** regardless of server language — see the migration reference. `mvn metaobjects:verify -Dmeta.verify.mode=db` is rejected (exit 2). diff --git a/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md b/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md index 2574655ff..35ac24804 100644 --- a/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md +++ b/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md @@ -9,10 +9,14 @@ committed snapshot — that snapshot loads BEFORE your own files, so a foreign abstract resolves via `extends` and a foreign node re-opens via `overlay: true` exactly like a local one. A dependency names one transport: `path` (a directory relative to the directory holding `.metaobjects/`), `npm` (an installed npm -package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`) -or `python` (an installed Python package by its import name, e.g. -`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`). For -`npm`/`python`, install the package with the project's package manager first; +package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`), +`python` (an installed Python package by its import name, e.g. +`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`), `maven` +(`{ "name": "acme-model", "maven": "com.acme:acme-model", "version": "1.0.0" }`, a JAR in the +local Maven repository) or `nuget` +(`{ "name": "acme-model", "nuget": "Acme.Model", "version": "1.0.0" }`, a package in the NuGet +global packages folder). For +`npm`/`python`/`maven`/`nuget`, install or restore the package with the project's package manager first; `meta deps sync` locates it, copies its shared model into the snapshot, and says what to install when it is missing. Prefer the package transport over a `path` into someone else's checkout when the publisher releases a package. Two rules are diff --git a/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md b/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md index 3d0cdc883..89050885d 100644 --- a/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md +++ b/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md @@ -41,10 +41,19 @@ replace those calls: an unmodified copy publishes the same bytes as the packaged generator. To publish through a package, point its `target` inside the package (an npm package's directory listed in `files`; a Python package's directory shipped as package data), run `meta gen`, then release the package as usual; consumers -declare an `npm` or `python` dependency on it. With no `version` option the +declare an `npm`, `python`, `maven` or `nuget` dependency on it. With no `version` option the manifest takes the nearest `package.json` version, else a `pyproject.toml` `[project]` version — pass `version` when neither is the package consumers install. -Only TypeScript can run it in Phase 1a. TypeScript, Python, Java, Kotlin (through -Java's loader and Maven plugin) and C# can *consume* a dependency, and only the -TypeScript toolchain can *publish* one. +TypeScript, Java, Kotlin and C# can *publish* with byte-identical output: the Java and Kotlin +`shared-model` generator runs through `mvn metaobjects:generate` (`SharedModelGenerator` / +`KotlinSharedModelGenerator`, args `name`, `include`, `exclude`, `files`, `version`; the version +defaults to the module ``); the C# one is `new SharedModelGenerator { ModelName, Include, +Files, OutDir }` in `codegen/Generators.cs` through `dotnet meta gen` (version from the project +``). Eject with `mvn metaobjects:eject -Dnames=shared-model -Dport=java|kotlin` or `dotnet +meta eject shared-model`. A JVM publisher ships the pair as the JAR's `metaobjects/` resources and a +C# publisher as the NuGet package's `metaobjects/` content; consumers declare +`{ "name": "x", "maven": "com.acme:model", "version": "1.0.0" }` or +`{ "name": "x", "nuget": "Acme.Model", "version": "1.0.0" }` (also `npm`/`python`/`path`). +TypeScript, Python, Java, Kotlin and C# *consume*; Python cannot publish. Node `meta deps sync` +remains the only writer of the lock and snapshot in every port. Full detail: `docs/features/metadata-dependencies.md`. diff --git a/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-verify/SKILL.md b/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-verify/SKILL.md index 54ffb4673..57b556e1f 100644 --- a/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-verify/SKILL.md +++ b/fixtures/agent-context-conformance/java-react/expected/.claude/skills/metaobjects-verify/SKILL.md @@ -166,15 +166,14 @@ with `ERR_DEPENDENCY_SNAPSHOT_STALE` naming the fix: run `meta deps sync`. if any reference isn't on the payload VO. This is the build-time gate for the prompt-construction pillar. -- **`--deps`** — dependency drift (FR-023, **Node `meta` only** — but **any - backend**, like `--db`: the check reads only `.metaobjects/config.json` and has - no backend dependency of its own). Re-resolves each declared dependency's `path` +- **`--deps`** — dependency drift (FR-023). Re-resolves each declared dependency right now and compares its installed artifact's hash against - `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Only - TypeScript and Python additionally LOAD the resulting snapshot and honour the - default-exclusion it implies — a Java/Kotlin/C# project can run this gate today - even though its own codegen can't yet consume a dependency. Never part of the - bare-`verify` default: it + `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Node + `meta` resolves every transport (`path`, `npm`, `python`, `maven`, `nuget`); the + Python, Java/Kotlin and C# checks resolve `path` only and report any other + transport `unresolved`, naming Node `meta deps check` (a check that cannot check + must not pass). Every port also loads the committed snapshot and honours the + default-exclusion it implies. Never part of the bare-`verify` default: it needs the publisher's `path` reachable, which CI checking out only your own repo may not have. Reports `current` / `drifted` / `unresolved` per dependency; `drifted` or `unresolved` fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT`, fix is @@ -188,7 +187,16 @@ port's own build tool, not the Node `meta`: | TS | `meta verify --codegen` | `meta verify --templates` | `meta verify --db ` | | Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=codegen` | `mvn metaobjects:verify -Dmeta.verify.mode=templates` | Node `meta verify --db` only | | C# | `dotnet meta verify --codegen` | `dotnet meta verify --templates` | Node `meta verify --db` only | -| Python | `metaobjects verify --codegen` | `metaobjects verify --templates` | Node `meta verify --db` only | +| Python | `metaobjects verify` (`--codegen` is in the default) | n/a | Node `meta verify --db` only | + +Dependency drift (`--deps`) per port: + +| Port | Dependency drift | +|---|---| +| TS | `meta deps check`, `meta verify --deps` | +| Python | `metaobjects deps check`, `metaobjects verify --deps` | +| Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=deps` | +| C# | `dotnet meta verify --deps` | Every non-TS port's `verify` rejects `--db` outright (exit 2, "schema verify is the migrate engine") — schema drift always runs through the Node `meta verify --db`, diff --git a/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-audit/references/python.md b/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-audit/references/python.md index 47beec1af..92c1d4250 100644 --- a/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-audit/references/python.md +++ b/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-audit/references/python.md @@ -40,8 +40,14 @@ metaobjects gen # run every target's generators (metaobjec metaobjects gen --generators entity # narrow to declared entries metaobjects verify --codegen # regenerate to temp, diff vs each committed outDir (bare default) metaobjects verify --templates # {{field}} refs vs payload VO +metaobjects deps check # shared-model dependencies vs deps.lock.json (also: verify --deps) ``` +`deps check` applies when the project declares `dependencies` in `.metaobjects/config.json`: it +hashes each `path` dependency against the lock and fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT` on +`drifted` or `unresolved` (a `maven`, `nuget`, `npm` or `python` dependency reports `unresolved`; +run the Node `meta deps check` for those). Python consumes a shared model but cannot publish one. + With no `metaobjects.config.yaml`, `gen` exits 2 and generates nothing. A target's `generators` takes stable generator names: `entity`, `routes`, `filter-allowlist`, `names`, `output-parser`, `extractor`, `output-prompt`, `render-helper`, `trace-helper`, diff --git a/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md b/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md index 2574655ff..35ac24804 100644 --- a/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md +++ b/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md @@ -9,10 +9,14 @@ committed snapshot — that snapshot loads BEFORE your own files, so a foreign abstract resolves via `extends` and a foreign node re-opens via `overlay: true` exactly like a local one. A dependency names one transport: `path` (a directory relative to the directory holding `.metaobjects/`), `npm` (an installed npm -package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`) -or `python` (an installed Python package by its import name, e.g. -`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`). For -`npm`/`python`, install the package with the project's package manager first; +package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`), +`python` (an installed Python package by its import name, e.g. +`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`), `maven` +(`{ "name": "acme-model", "maven": "com.acme:acme-model", "version": "1.0.0" }`, a JAR in the +local Maven repository) or `nuget` +(`{ "name": "acme-model", "nuget": "Acme.Model", "version": "1.0.0" }`, a package in the NuGet +global packages folder). For +`npm`/`python`/`maven`/`nuget`, install or restore the package with the project's package manager first; `meta deps sync` locates it, copies its shared model into the snapshot, and says what to install when it is missing. Prefer the package transport over a `path` into someone else's checkout when the publisher releases a package. Two rules are diff --git a/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md b/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md index 3d0cdc883..89050885d 100644 --- a/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md +++ b/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md @@ -41,10 +41,19 @@ replace those calls: an unmodified copy publishes the same bytes as the packaged generator. To publish through a package, point its `target` inside the package (an npm package's directory listed in `files`; a Python package's directory shipped as package data), run `meta gen`, then release the package as usual; consumers -declare an `npm` or `python` dependency on it. With no `version` option the +declare an `npm`, `python`, `maven` or `nuget` dependency on it. With no `version` option the manifest takes the nearest `package.json` version, else a `pyproject.toml` `[project]` version — pass `version` when neither is the package consumers install. -Only TypeScript can run it in Phase 1a. TypeScript, Python, Java, Kotlin (through -Java's loader and Maven plugin) and C# can *consume* a dependency, and only the -TypeScript toolchain can *publish* one. +TypeScript, Java, Kotlin and C# can *publish* with byte-identical output: the Java and Kotlin +`shared-model` generator runs through `mvn metaobjects:generate` (`SharedModelGenerator` / +`KotlinSharedModelGenerator`, args `name`, `include`, `exclude`, `files`, `version`; the version +defaults to the module ``); the C# one is `new SharedModelGenerator { ModelName, Include, +Files, OutDir }` in `codegen/Generators.cs` through `dotnet meta gen` (version from the project +``). Eject with `mvn metaobjects:eject -Dnames=shared-model -Dport=java|kotlin` or `dotnet +meta eject shared-model`. A JVM publisher ships the pair as the JAR's `metaobjects/` resources and a +C# publisher as the NuGet package's `metaobjects/` content; consumers declare +`{ "name": "x", "maven": "com.acme:model", "version": "1.0.0" }` or +`{ "name": "x", "nuget": "Acme.Model", "version": "1.0.0" }` (also `npm`/`python`/`path`). +TypeScript, Python, Java, Kotlin and C# *consume*; Python cannot publish. Node `meta deps sync` +remains the only writer of the lock and snapshot in every port. Full detail: `docs/features/metadata-dependencies.md`. diff --git a/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-verify/SKILL.md b/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-verify/SKILL.md index 54ffb4673..57b556e1f 100644 --- a/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-verify/SKILL.md +++ b/fixtures/agent-context-conformance/python/expected/.claude/skills/metaobjects-verify/SKILL.md @@ -166,15 +166,14 @@ with `ERR_DEPENDENCY_SNAPSHOT_STALE` naming the fix: run `meta deps sync`. if any reference isn't on the payload VO. This is the build-time gate for the prompt-construction pillar. -- **`--deps`** — dependency drift (FR-023, **Node `meta` only** — but **any - backend**, like `--db`: the check reads only `.metaobjects/config.json` and has - no backend dependency of its own). Re-resolves each declared dependency's `path` +- **`--deps`** — dependency drift (FR-023). Re-resolves each declared dependency right now and compares its installed artifact's hash against - `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Only - TypeScript and Python additionally LOAD the resulting snapshot and honour the - default-exclusion it implies — a Java/Kotlin/C# project can run this gate today - even though its own codegen can't yet consume a dependency. Never part of the - bare-`verify` default: it + `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Node + `meta` resolves every transport (`path`, `npm`, `python`, `maven`, `nuget`); the + Python, Java/Kotlin and C# checks resolve `path` only and report any other + transport `unresolved`, naming Node `meta deps check` (a check that cannot check + must not pass). Every port also loads the committed snapshot and honours the + default-exclusion it implies. Never part of the bare-`verify` default: it needs the publisher's `path` reachable, which CI checking out only your own repo may not have. Reports `current` / `drifted` / `unresolved` per dependency; `drifted` or `unresolved` fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT`, fix is @@ -188,7 +187,16 @@ port's own build tool, not the Node `meta`: | TS | `meta verify --codegen` | `meta verify --templates` | `meta verify --db ` | | Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=codegen` | `mvn metaobjects:verify -Dmeta.verify.mode=templates` | Node `meta verify --db` only | | C# | `dotnet meta verify --codegen` | `dotnet meta verify --templates` | Node `meta verify --db` only | -| Python | `metaobjects verify --codegen` | `metaobjects verify --templates` | Node `meta verify --db` only | +| Python | `metaobjects verify` (`--codegen` is in the default) | n/a | Node `meta verify --db` only | + +Dependency drift (`--deps`) per port: + +| Port | Dependency drift | +|---|---| +| TS | `meta deps check`, `meta verify --deps` | +| Python | `metaobjects deps check`, `metaobjects verify --deps` | +| Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=deps` | +| C# | `dotnet meta verify --deps` | Every non-TS port's `verify` rejects `--db` outright (exit 2, "schema verify is the migrate engine") — schema drift always runs through the Node `meta verify --db`, diff --git a/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md b/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md index 2574655ff..35ac24804 100644 --- a/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md +++ b/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md @@ -9,10 +9,14 @@ committed snapshot — that snapshot loads BEFORE your own files, so a foreign abstract resolves via `extends` and a foreign node re-opens via `overlay: true` exactly like a local one. A dependency names one transport: `path` (a directory relative to the directory holding `.metaobjects/`), `npm` (an installed npm -package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`) -or `python` (an installed Python package by its import name, e.g. -`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`). For -`npm`/`python`, install the package with the project's package manager first; +package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`), +`python` (an installed Python package by its import name, e.g. +`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`), `maven` +(`{ "name": "acme-model", "maven": "com.acme:acme-model", "version": "1.0.0" }`, a JAR in the +local Maven repository) or `nuget` +(`{ "name": "acme-model", "nuget": "Acme.Model", "version": "1.0.0" }`, a package in the NuGet +global packages folder). For +`npm`/`python`/`maven`/`nuget`, install or restore the package with the project's package manager first; `meta deps sync` locates it, copies its shared model into the snapshot, and says what to install when it is missing. Prefer the package transport over a `path` into someone else's checkout when the publisher releases a package. Two rules are diff --git a/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md b/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md index 3d0cdc883..89050885d 100644 --- a/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md +++ b/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md @@ -41,10 +41,19 @@ replace those calls: an unmodified copy publishes the same bytes as the packaged generator. To publish through a package, point its `target` inside the package (an npm package's directory listed in `files`; a Python package's directory shipped as package data), run `meta gen`, then release the package as usual; consumers -declare an `npm` or `python` dependency on it. With no `version` option the +declare an `npm`, `python`, `maven` or `nuget` dependency on it. With no `version` option the manifest takes the nearest `package.json` version, else a `pyproject.toml` `[project]` version — pass `version` when neither is the package consumers install. -Only TypeScript can run it in Phase 1a. TypeScript, Python, Java, Kotlin (through -Java's loader and Maven plugin) and C# can *consume* a dependency, and only the -TypeScript toolchain can *publish* one. +TypeScript, Java, Kotlin and C# can *publish* with byte-identical output: the Java and Kotlin +`shared-model` generator runs through `mvn metaobjects:generate` (`SharedModelGenerator` / +`KotlinSharedModelGenerator`, args `name`, `include`, `exclude`, `files`, `version`; the version +defaults to the module ``); the C# one is `new SharedModelGenerator { ModelName, Include, +Files, OutDir }` in `codegen/Generators.cs` through `dotnet meta gen` (version from the project +``). Eject with `mvn metaobjects:eject -Dnames=shared-model -Dport=java|kotlin` or `dotnet +meta eject shared-model`. A JVM publisher ships the pair as the JAR's `metaobjects/` resources and a +C# publisher as the NuGet package's `metaobjects/` content; consumers declare +`{ "name": "x", "maven": "com.acme:model", "version": "1.0.0" }` or +`{ "name": "x", "nuget": "Acme.Model", "version": "1.0.0" }` (also `npm`/`python`/`path`). +TypeScript, Python, Java, Kotlin and C# *consume*; Python cannot publish. Node `meta deps sync` +remains the only writer of the lock and snapshot in every port. Full detail: `docs/features/metadata-dependencies.md`. diff --git a/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-verify/SKILL.md b/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-verify/SKILL.md index 54ffb4673..57b556e1f 100644 --- a/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-verify/SKILL.md +++ b/fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-verify/SKILL.md @@ -166,15 +166,14 @@ with `ERR_DEPENDENCY_SNAPSHOT_STALE` naming the fix: run `meta deps sync`. if any reference isn't on the payload VO. This is the build-time gate for the prompt-construction pillar. -- **`--deps`** — dependency drift (FR-023, **Node `meta` only** — but **any - backend**, like `--db`: the check reads only `.metaobjects/config.json` and has - no backend dependency of its own). Re-resolves each declared dependency's `path` +- **`--deps`** — dependency drift (FR-023). Re-resolves each declared dependency right now and compares its installed artifact's hash against - `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Only - TypeScript and Python additionally LOAD the resulting snapshot and honour the - default-exclusion it implies — a Java/Kotlin/C# project can run this gate today - even though its own codegen can't yet consume a dependency. Never part of the - bare-`verify` default: it + `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Node + `meta` resolves every transport (`path`, `npm`, `python`, `maven`, `nuget`); the + Python, Java/Kotlin and C# checks resolve `path` only and report any other + transport `unresolved`, naming Node `meta deps check` (a check that cannot check + must not pass). Every port also loads the committed snapshot and honours the + default-exclusion it implies. Never part of the bare-`verify` default: it needs the publisher's `path` reachable, which CI checking out only your own repo may not have. Reports `current` / `drifted` / `unresolved` per dependency; `drifted` or `unresolved` fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT`, fix is @@ -188,7 +187,16 @@ port's own build tool, not the Node `meta`: | TS | `meta verify --codegen` | `meta verify --templates` | `meta verify --db ` | | Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=codegen` | `mvn metaobjects:verify -Dmeta.verify.mode=templates` | Node `meta verify --db` only | | C# | `dotnet meta verify --codegen` | `dotnet meta verify --templates` | Node `meta verify --db` only | -| Python | `metaobjects verify --codegen` | `metaobjects verify --templates` | Node `meta verify --db` only | +| Python | `metaobjects verify` (`--codegen` is in the default) | n/a | Node `meta verify --db` only | + +Dependency drift (`--deps`) per port: + +| Port | Dependency drift | +|---|---| +| TS | `meta deps check`, `meta verify --deps` | +| Python | `metaobjects deps check`, `metaobjects verify --deps` | +| Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=deps` | +| C# | `dotnet meta verify --deps` | Every non-TS port's `verify` rejects `--db` outright (exit 2, "schema verify is the migrate engine") — schema drift always runs through the Node `meta verify --db`, diff --git a/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md b/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md index 2574655ff..35ac24804 100644 --- a/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md +++ b/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-authoring/references/metadata-dependencies.md @@ -9,10 +9,14 @@ committed snapshot — that snapshot loads BEFORE your own files, so a foreign abstract resolves via `extends` and a foreign node re-opens via `overlay: true` exactly like a local one. A dependency names one transport: `path` (a directory relative to the directory holding `.metaobjects/`), `npm` (an installed npm -package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`) -or `python` (an installed Python package by its import name, e.g. -`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`). For -`npm`/`python`, install the package with the project's package manager first; +package, e.g. `{ "name": "acme-model", "npm": "@acme/model", "dir": "metaobjects" }`), +`python` (an installed Python package by its import name, e.g. +`{ "name": "acme-model", "python": "acme_model", "dir": "metaobjects" }`), `maven` +(`{ "name": "acme-model", "maven": "com.acme:acme-model", "version": "1.0.0" }`, a JAR in the +local Maven repository) or `nuget` +(`{ "name": "acme-model", "nuget": "Acme.Model", "version": "1.0.0" }`, a package in the NuGet +global packages folder). For +`npm`/`python`/`maven`/`nuget`, install or restore the package with the project's package manager first; `meta deps sync` locates it, copies its shared model into the snapshot, and says what to install when it is missing. Prefer the package transport over a `path` into someone else's checkout when the publisher releases a package. Two rules are diff --git a/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md b/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md index 3d0cdc883..89050885d 100644 --- a/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md +++ b/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-codegen/references/dependencies-and-shared-models.md @@ -41,10 +41,19 @@ replace those calls: an unmodified copy publishes the same bytes as the packaged generator. To publish through a package, point its `target` inside the package (an npm package's directory listed in `files`; a Python package's directory shipped as package data), run `meta gen`, then release the package as usual; consumers -declare an `npm` or `python` dependency on it. With no `version` option the +declare an `npm`, `python`, `maven` or `nuget` dependency on it. With no `version` option the manifest takes the nearest `package.json` version, else a `pyproject.toml` `[project]` version — pass `version` when neither is the package consumers install. -Only TypeScript can run it in Phase 1a. TypeScript, Python, Java, Kotlin (through -Java's loader and Maven plugin) and C# can *consume* a dependency, and only the -TypeScript toolchain can *publish* one. +TypeScript, Java, Kotlin and C# can *publish* with byte-identical output: the Java and Kotlin +`shared-model` generator runs through `mvn metaobjects:generate` (`SharedModelGenerator` / +`KotlinSharedModelGenerator`, args `name`, `include`, `exclude`, `files`, `version`; the version +defaults to the module ``); the C# one is `new SharedModelGenerator { ModelName, Include, +Files, OutDir }` in `codegen/Generators.cs` through `dotnet meta gen` (version from the project +``). Eject with `mvn metaobjects:eject -Dnames=shared-model -Dport=java|kotlin` or `dotnet +meta eject shared-model`. A JVM publisher ships the pair as the JAR's `metaobjects/` resources and a +C# publisher as the NuGet package's `metaobjects/` content; consumers declare +`{ "name": "x", "maven": "com.acme:model", "version": "1.0.0" }` or +`{ "name": "x", "nuget": "Acme.Model", "version": "1.0.0" }` (also `npm`/`python`/`path`). +TypeScript, Python, Java, Kotlin and C# *consume*; Python cannot publish. Node `meta deps sync` +remains the only writer of the lock and snapshot in every port. Full detail: `docs/features/metadata-dependencies.md`. diff --git a/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-verify/SKILL.md b/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-verify/SKILL.md index 54ffb4673..57b556e1f 100644 --- a/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-verify/SKILL.md +++ b/fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-verify/SKILL.md @@ -166,15 +166,14 @@ with `ERR_DEPENDENCY_SNAPSHOT_STALE` naming the fix: run `meta deps sync`. if any reference isn't on the payload VO. This is the build-time gate for the prompt-construction pillar. -- **`--deps`** — dependency drift (FR-023, **Node `meta` only** — but **any - backend**, like `--db`: the check reads only `.metaobjects/config.json` and has - no backend dependency of its own). Re-resolves each declared dependency's `path` +- **`--deps`** — dependency drift (FR-023). Re-resolves each declared dependency right now and compares its installed artifact's hash against - `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Only - TypeScript and Python additionally LOAD the resulting snapshot and honour the - default-exclusion it implies — a Java/Kotlin/C# project can run this gate today - even though its own codegen can't yet consume a dependency. Never part of the - bare-`verify` default: it + `.metaobjects/deps.lock.json` — the same comparison `meta deps check` runs. Node + `meta` resolves every transport (`path`, `npm`, `python`, `maven`, `nuget`); the + Python, Java/Kotlin and C# checks resolve `path` only and report any other + transport `unresolved`, naming Node `meta deps check` (a check that cannot check + must not pass). Every port also loads the committed snapshot and honours the + default-exclusion it implies. Never part of the bare-`verify` default: it needs the publisher's `path` reachable, which CI checking out only your own repo may not have. Reports `current` / `drifted` / `unresolved` per dependency; `drifted` or `unresolved` fails with `ERR_DEPENDENCY_UPSTREAM_DRIFT`, fix is @@ -188,7 +187,16 @@ port's own build tool, not the Node `meta`: | TS | `meta verify --codegen` | `meta verify --templates` | `meta verify --db ` | | Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=codegen` | `mvn metaobjects:verify -Dmeta.verify.mode=templates` | Node `meta verify --db` only | | C# | `dotnet meta verify --codegen` | `dotnet meta verify --templates` | Node `meta verify --db` only | -| Python | `metaobjects verify --codegen` | `metaobjects verify --templates` | Node `meta verify --db` only | +| Python | `metaobjects verify` (`--codegen` is in the default) | n/a | Node `meta verify --db` only | + +Dependency drift (`--deps`) per port: + +| Port | Dependency drift | +|---|---| +| TS | `meta deps check`, `meta verify --deps` | +| Python | `metaobjects deps check`, `metaobjects verify --deps` | +| Java / Kotlin | `mvn metaobjects:verify -Dmeta.verify.mode=deps` | +| C# | `dotnet meta verify --deps` | Every non-TS port's `verify` rejects `--db` outright (exit 2, "schema verify is the migrate engine") — schema drift always runs through the Node `meta verify --db`,