You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit eaff41d
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: AGENTS.md
+5-3Lines changed: 5 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,19 +6,21 @@ MetaObjects is a **cross-language metadata standard** for declaring typed entity
6
6
7
7
The metamodel is the **durable spine**; generated code is the **disposable artifact**. Substrate is local-first: typed metadata lives in your repo, generated code is idiomatic per-language output that runs without any MetaObjects dependency at runtime. If `@metaobjectsdev/*` disappears tomorrow, you keep working code.
8
8
9
-
## Five pillars
9
+
## Six pillars
10
10
11
-
The first four ship per-language today across the five ports (TS / C# / Java / Python / Kotlin), with cross-port conformance corpora verifying byte-identical behavior. The fifth ships its vocabulary and its `verify` checks in every port, and its test scaffolding in TypeScript only:
11
+
The first four ship per-language today across the five ports (TS / C# / Java / Python / Kotlin), with cross-port conformance corpora verifying byte-identical behavior. The fifth ships its vocabulary and its `verify` checks in every port, and its test scaffolding in TypeScript only. The sixth is content the other five compose, shipped as named opt-in artifacts:
12
12
13
13
1.**Codegen** — emit idiomatic per-language code (Drizzle/Zod + Fastify for TS, EF Core + ASP.NET for C#, Spring REST + DTO + Repository for Java via `codegen-spring`, Pydantic + FastAPI for Python, KotlinPoet + Exposed + Spring for Kotlin via `codegen-kotlin`). Hand-edit-preserving regen via three-way merge.
14
14
2.**Runtime metadata** — load metadata at runtime, drive behavior dynamically (CRUD, validation, relationships, dynamic admin UIs, LLM tool registration). On Kysely (TS), a DB-API 2 driver via ObjectManager (Python), modernized JDBC + Spring-tx via OMDB (Java), Exposed (Kotlin), EF Core (C#).
15
15
3.**Drift detection** — `meta verify` catches divergence between code and metadata (covers entity codegen, prompt templates, output parsers, schema). Quality-of-life on top of codegen + runtime.
16
16
4. **Prompt construction** — a prompt is code, not a string scattered across services. Declare a prompt's payload as a typed projection (payload bloat becomes a diff), keep its text external and provider-resolved, and render it deterministically: snapshot-testable, cache-stable (no whitespace change silently breaking exact-prefix prompt-cache hits), and drift-checked at build time so a renamed field can't degrade a prompt. Conformance-gated, so the guarantee holds in every language port. **Render + payload-VO codegen + `verify` + parser-on-receipt for a *responding* `template.prompt` — one carrying `@responseRef` (FR-006) — + the output-format prompt fragment & tolerant `extract` parser (FR-010) ship in all five ports today** (since 0.24.0 the whole inbound tier keys off `@responseRef`; a `template.output` is outbound-only and emits no parser — ADR-0052) — the library-side building blocks of the pillar are complete. The one remaining library-side piece is MCP exposure of declared prompts/tools (see `spec/roadmap.md`); the application-level consolidation (eval harness, end-to-end declared-prompt orchestration) and consumer adoption are exercised in adopter projects, not in this library repo. Designed in `docs/superpowers/specs/2026-05-22-fr-004-cross-language-prompt-construction-design.md`.
17
17
5. **Requirements and testing** — declare what the software is supposed to *do* in the same model as the entities, so a capability claim is checkable instead of prose. The other four pillars keep the code honest about the *model*; this one asks whether the thing you said the software does is actually built — an absence no test can fail on, because a test exercises code that exists. `requirement.functional` (fails when *nothing* implements it) and `requirement.architectural` (fails when something *violates* it) are registered vocabulary in all five ports, with the loader enforcing the closed `@status` enum. `@implementedBy` is **resolved, not trusted** — it names a real member of the real model, so a claim whose implementation was renamed or deleted fails the build instead of going quietly stale. `meta verify` reports the ledger on every run (unresolved links, entities no claim covers, gaps recorded versus gaps nobody has ruled on) plus an authoring lint whose findings can never fail a build; `meta docs` renders it for humans and for agents. **The port split, stated exactly: the vocabulary and the `verify` checks are cross-port; `requirementTests()` — which scaffolds a test stub per claim — is TypeScript-only.** A project that declares no `requirement.*` nodes sees no change at all. Note the standing carve-out: `agent-context/skills/metaobjects-fit-assessment/SKILL.md` deliberately does NOT treat `requirement.*` as an assessment axis — see the ruling in that file before "finishing the job" there.
18
18
19
+
6. **Libraries** — reusable declared design, shipped as metadata and opted into by name (`"libraries": ["iam"]` in `.metaobjects/config.json`). Not a sixth verb: a library is the **reuse unit that composes the other five** — entities, requirements, the generators its design implies, its runtime packages — as one named, opt-in, drift-gated artifact. What makes it a pillar rather than a folder of YAML is the fifth: without requirements a library is a schema snippet; with them it is design an adopter's build is held to, which is the same test the requirements pillar passes (*does it change what an agent can be checked against?*). **A library is LAYERED and its core layer is INERT** — the core declares no `source.rdb`, and a sourceless object generates nothing and migrates to nothing (#248), so `["iam"]` adds zero tables and zero generated code while making the design present and resolvable; `["iam", "iam/db"]` is the separate opt-in that proposes the schema. **Copy is the expected mode** (`meta eject <library>` — ADR-0034's ruling applied to metadata), and an ejected copy still named in `libraries` is refused at load (`ERR_LIBRARY_PACKAGE_COLLISION`) rather than merging asymmetrically. Object coverage activates on ADOPTER-authored requirements only, so a library cannot volunteer a project for a gate it did not ask for. `iam` (preview) and `ai` (stable) ship today; rows appear in `meta gen --list` beside the generators. See [docs/features/libraries.md](docs/features/libraries.md) and `docs/superpowers/specs/2026-09-13-fr-043-feature-and-nfr-packages-design.md`.
20
+
19
21
## Status
20
22
21
-
_Last refreshed 2026-09-12._
23
+
_Last refreshed 2026-09-13._
22
24
23
25
**1.0 gating — the quiet period is RETIRED (2026-09-06).**`docs/1.0-readiness.md` §G3 no
24
26
longer asks for "one coordinated release with no metamodel-breaking change." It measured a
Copy file name to clipboardExpand all lines: agent-context/skills/metaobjects-audit/SKILL.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -351,7 +351,7 @@ Per finding: `file:line` → what → generated-equivalent exists? → recommend
351
351
352
352
**Score only where a constant actually exists.** A fact declared in the project's CODEGEN CONFIG rather than in metadata — a bespoke route mount path, a hand-chosen JSON envelope key — is genuinely spelled twice when a client re-types it, but no generated constant holds it. That is a GENERATOR GAP, reported as one, never a literal-site finding: never invent a constant that the emitters do not emit.
353
353
354
-
**No verify subverb sees this** — `--codegen` diffs generated files, `--db` compares schema to metadata — so this audit is the only gate. Remedy: reference the constant — but **check the artifact is emitted at all before scoring the literals, because on THREE of five ports an existing project emits none**. C# and Python have a real default suite and get it by upgrading; TypeScript's `generators: [...]` and the JVM's `<generators>` are each the COMPLETE list, so`meta init`scaffolding `namesFile()` covers only a project initialized at 1.0 and upgrading the package never edits a config written earlier. Where no artifact exists, the un-wired generator is the FIRST finding and the first remedy (`namesFile()` on TS after `meta eject names`; `SpringNamesGenerator` / `KotlinNamesGenerator` in the pom) — score the literals under it rather than as N independent findings, since one config line fixes the cause and generated code stops embedding the names too.
354
+
**No verify subverb sees this** — `--codegen` diffs generated files, `--db` compares schema to metadata — so this audit is the only gate. Remedy: reference the constant — but **check the artifact is emitted at all before scoring the literals, because on ALL FIVE ports an existing project emits none until it asks**. ADR-0034 Amendment 2 made codegen opt-in everywhere: C# and Python require `--generators`, TypeScript's `generators: [...]` and the JVM's `<generators>` are each the COMPLETE list, and`meta init`scaffolds `generators: []` — so no port begins emitting this artifact merely because the package was upgraded. Where no artifact exists, the un-wired generator is the FIRST finding and the first remedy (`namesFile()` on TS after `meta eject names`; `SpringNamesGenerator` / `KotlinNamesGenerator` in the pom) — score the literals under it rather than as N independent findings, since one config line fixes the cause and generated code stops embedding the names too.
355
355
356
356
**Report TWO numbers for this signature, always, and never just the first: (a) is the artifact EMITTED, and (b) how many of the literal sites actually IMPORT it — the adoption ratio, as `<adopted>/<total> sites`.** Emission is the cheap half and it is the half that gets done: measured on an adopter whose audit proved the artifact emitted correctly, ran the generator to show it, and then adopted it at **0 of 53 sites** (37 table + 16 column). Wiring the generator changes the scorecard; it changes nothing a reader of the code experiences, because the second spelling is still the one every query uses. An audit that reports only (a) makes the estate look upgraded while every literal it found is still there — so a project that emits the artifact and imports it nowhere scores WORSE than one that has not started, not better, because it now carries a third spelling that claims to be the source of truth.
Copy file name to clipboardExpand all lines: agent-context/skills/metaobjects-audit/references/csharp.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -51,7 +51,7 @@ rejected (exit 2).
51
51
|`FromSqlInterpolated(` outside `.g.cs`| stored-proc call — candidate for the `callable` generator |
52
52
|`// keep in sync with` / `// mirrors the`| second-source-of-truth comment — always a finding |
53
53
|`HasPrecision(` hand-coded |`field.decimal` with `@precision`/`@scale` drives this from the `entity` generator |
54
-
| a table/column string in raw-SQL EF calls, or `nameof(Entity.Prop)` standing in for a column | second spelling of a declared physical name — reference `<Entity>Names.g.cs` (`AuthorNames.SourcePrimaryTable` / `<Field>Column`, default suite — `Names.Name` is the OBJECT's name, not the table); an EF property inside LINQ is the typed handle — correct |
54
+
| a table/column string in raw-SQL EF calls, or `nameof(Entity.Prop)` standing in for a column | second spelling of a declared physical name — reference `<Entity>Names.g.cs` (`AuthorNames.SourcePrimaryTable` / `<Field>Column`, emitted when `names` is named in `--generators` — `Names.Name` is the OBJECT's name, not the table); an EF property inside LINQ is the typed handle — correct |
55
55
56
56
---
57
57
@@ -66,7 +66,7 @@ selection uses stable names via `dotnet meta gen --generators <names>`, over a
66
66
**So do not score a C# project down for "not owning its generators", and do not
67
67
recommend writing one.** The customization path here is the **declarative template**:
68
68
`dotnet meta gen --template-spec <json> --template-root <dir>`, whose entries append to
69
-
the default suite. A finding of the form "the built-ins do not emit the shape this
69
+
your `--generators` selection. A finding of the form "the built-ins do not emit the shape this
70
70
project needs" resolves to a template-spec, not to generator code. Worked example with
0 commit comments