Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,25 @@ Each item below is described in full under Added, Changed or Fixed; this list is

### Added

- **A working loop first in the agent context.** The always-on file `meta init` scaffolds
(`.metaobjects/AGENTS.md` and `CLAUDE.md`) now opens with the whole loop for the declared
stack, in order: configure and run the generators (one step per declared server, with the
import or class names to wire, plus the web client when one is declared), the schema
(`meta migrate --from-db` for the first migration, `apply-pending` at boot, and a later
change with `--rename-column`, `--rename-table` and `--allow`), requirements, and the verify
commands to run before calling work done. It shrinks from about 19 KB to about 5 KB. The
principles it carried move, word for word, to `metaobjects-codegen/references/principles.md`,
and the port-sync and upgrade paragraphs to `metaobjects-verify/references/upgrading.md`. It
no longer tells an agent to read a skill's `SKILL.md` by path, and says the loop needs no
skill. The skill trigger evals gain mid-task cases.
- **`meta init --dialect sqlite|postgres|mysql|d1`.** Writes the codegen `dialect` and, for
sqlite, postgres and d1, `migrate.dialect`, and the next steps print that dialect's first
migration. `--dialect d1` is `--d1`; the two together with different dialects are refused.
MySQL is codegen only, as before: the next steps say `meta migrate` does not own its schema.
- **`meta gen` names `requirementTests()` when nothing tests the requirements.** A model that
declares `requirement.*` nodes, with no `requirement-tests` generator wired, gets one advisory
line naming the import. The exit code is unchanged.

- **Cross-port vocabulary that only some ports implement so far (`implementedIn`).** A registry
type or attr may name the ports that implement it so far (`"implementedIn": ["typescript"]` on
its `spec/metamodel` entry, carried into the registry manifest). It is still cross-port
Expand Down Expand Up @@ -499,6 +518,18 @@ Each item below is described in full under Added, Changed or Fixed; this list is

### Changed

- **The requirements reference pages install in every stack.** They used to install only when
`meta init` saw a `requirement.*` node, which a new project has not written yet, so a project
that declared requirements later had skills pointing at pages that were not there. `meta gen`
and `meta verify` now say so for a context scaffolded that way, and name
`meta init --docs-only --refresh-docs`.
- **A shorter scaffolded `metaobjects.config.ts` comment.** It now shows the import line for the
usual data layer (`entityFile`, `namesFile`, `barrel`) and the catalog command, and drops the
rest.
- **`meta gen --list` off a terminal is unchanged.** Its default there stays the TOON document,
which tools and the skills parse for `wire.import` and `layer`; the agent context gives a
one-line filter for a compact view instead.

- **A new top-level requirement declared into a dependency's package is refused** with
`ERR_DEPENDENCY_PACKAGE_NOT_OWNED`, as a new object there already was. An overlay of the
dependency's own requirement is still accepted.
Expand Down
7 changes: 4 additions & 3 deletions agent-context/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ the slim always-on Markdown (`.metaobjects/AGENTS.md` + `CLAUDE.md`) and the six
`metaobjects-*` Claude skills (each a universal `SKILL.md` plus the
`references/<token>.md` fragments matching the project's resolved stack).

- `servers/<lang>.meta.json` — per-server install + codegen command (drives the always-on).
- `templates/always-on.md.mustache` — the slim always-on body (`{{stackLine}}`, `{{codegenCommand}}`).
- `servers/<lang>.meta.json` — per-server install, codegen command and the always-on's verify step (`verifyStep`).
- `templates/always-on.md.mustache` — the slim always-on body: a working loop first (`{{stackLine}}`, `{{stackLoops}}`, `{{verifySteps}}`), then the rules. The full principles it shortens live in `metaobjects-codegen/references/principles.md`.
- `templates/loops/<server>.md`, `templates/loops/client.md` — the generate steps of that loop, one per declared server (and one for a web client), concatenated by the assembler.
- `skills/<skill>/SKILL.md` — universal skill body.
- `skills/<skill>/references/<token>.md` — language/framework or concern fragment; installed iff `<token>` is in the stack (`Stack.tokens`; concern tokens are OBSERVED from project state, e.g. `requirements` for a project declaring `requirement.*` nodes — see `SDK`'s `CONCERN_TOKENS`).
- `skills/<skill>/references/<token>.md` — language/framework fragment; installed iff `<token>` is in the stack (`Stack.tokens`). The requirements pages are universal topic files: they install in every stack, because whether a project declares `requirement.*` nodes changes after `meta init` runs.
- `skills/<skill>/references/<token>-<topic>.md` — a topic split out of a `<token>.md` fragment; scoped by the same token.
- `skills/<skill>/references/<topic>.md` — any other name is a universal topic file and installs in every stack; the skill's `SKILL.md` says when to open it.

Expand Down
9 changes: 8 additions & 1 deletion agent-context/evals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ one-message prompt plus a `tool_used: Skill` grader: positive cases require the
fire, negative cases (near-misses: LLM code in a project that does not use MetaObjects
prompts, model edits that need no generated output) forbid it.

Most cases are a fresh request. The `*-midtask-*` cases are the shape real work takes: the
prompt states what has already been done in the session (entities declared, `meta gen` run, a
migration applied) and then the next step. A skill that fires only on an opening request and
never once the agent is past the loop in the always-on file is the failure they catch, and the
negative ones catch the opposite: a skill loaded for a step the loop already covers (writing
business logic over generated types, running a rename migration).

- `skill-triggers/<skill>/<NN>-pos-*|neg-*/` — `prompt.md` and `graders/trigger.md`, in the
`claude plugin eval` case format.
- `run-skill-triggers.sh` — wraps `agent-context/skills` in a throwaway plugin (all seven
Expand All @@ -18,7 +25,7 @@ prompts, model edits that need no generated output) forbid it.
agent-context/evals/run-skill-triggers.sh <out-dir>
```

It starts real Claude sessions on your own login (25 cases x 3 runs = 75 sessions, a few
It starts real Claude sessions on your own login (31 cases x 3 runs = 93 sessions, a few
minutes with `-j 4`) and writes `<out-dir>/result.json`. Use `--case '<glob>'` to run a
subset. It is manual-only and not part of CI, because model behaviour is not deterministic.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
type: tool_used
tool: Skill
input_match: metaobjects-codegen
min: 1
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
max_turns: 3
timeout_seconds: 180
allowed_tools: [Skill]
runs: 3
---

This project uses MetaObjects (it has .metaobjects/config.json and a metaobjects/ directory of meta.*.json files). Progress so far: you added the Order and OrderLine entities, ran `npx meta gen`, and wired the generated Drizzle tables into the service. The typecheck now fails because the generated OrderLine.ts exports `orderLineInsertSchema` and the service expects `OrderLineInsert` as a named type next to it. Make the generated file export that type on every regen.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
type: tool_used
tool: Skill
input_match: metaobjects-codegen
min: 1
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
max_turns: 3
timeout_seconds: 180
allowed_tools: [Skill]
runs: 3
---

This project uses MetaObjects (it has .metaobjects/config.json and a metaobjects/ directory of meta.*.json files). Progress so far: entities are declared, `npx meta gen` writes the Drizzle tables, and the first migration is applied. Next on the task list: the admin service needs a TypeScript map from each entity name to its list of searchable column names, kept in step with the metadata. Nothing in `meta gen --list` emits it. Produce it.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
type: tool_used
tool: Skill
input_match: metaobjects-codegen
min: 0
max: 0
arm: both
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
max_turns: 3
timeout_seconds: 180
allowed_tools: [Skill]
runs: 3
---

This project uses MetaObjects (it has .metaobjects/config.json and a metaobjects/ directory of meta.*.json files). Progress so far: the Invoice entity is declared, `npx meta gen` wrote Invoice.ts with its Drizzle table and Zod schemas, and the migration is applied. Next: in src/billing/totals.ts, write the function that sums an invoice's lines, applies the customer's discount percentage and rounds to cents.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
type: tool_used
tool: Skill
input_match: metaobjects-codegen
min: 0
max: 0
arm: both
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
max_turns: 3
timeout_seconds: 180
allowed_tools: [Skill]
runs: 3
---

This project uses MetaObjects (it has .metaobjects/config.json and a metaobjects/ directory of meta.*.json files). Progress so far: you renamed the Customer field `fullName` to `displayName` in metaobjects/meta.crm.json and regenerated. Now write the migration for it with `npx meta migrate` so the existing data in that column is kept.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
type: tool_used
tool: Skill
input_match: metaobjects-prompts
min: 1
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
max_turns: 3
timeout_seconds: 180
allowed_tools: [Skill]
runs: 3
---

This project uses MetaObjects, including declared prompt templates (template.prompt nodes under metaobjects/ and their text under prompts/). Progress so far: you built the TicketSummary endpoint and it works. While wiring it you wrote the LLM call in src/tickets/summarize.ts with the prompt as a template literal that interpolates ticket.title, ticket.body and the last five comments, and you parse the reply with JSON.parse. Before you commit, bring that call in line with how this project does prompts.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
type: tool_used
tool: Skill
input_match: metaobjects-prompts
min: 0
max: 0
arm: both
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
max_turns: 3
timeout_seconds: 180
allowed_tools: [Skill]
runs: 3
---

This project uses MetaObjects, including declared prompt templates (template.prompt nodes under metaobjects/ and their text under prompts/). Progress so far: the TicketSummary prompt is declared, rendered and parsed through the generated code, and its tests pass. Next: the HTTP client that sends the rendered prompt to the model sometimes gets a 529. Add a retry with exponential backoff, three attempts, around that client call in src/llm/client.ts.
5 changes: 1 addition & 4 deletions agent-context/servers/csharp.meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,5 @@
"displayName": "C#",
"install": "install the MetaObjects .NET tool (dotnet tool install) + add the MetaObjects.Codegen package",
"codegenCommand": "dotnet meta gen",
"docsCommand": "dotnet meta gen",
"docsCondition": " (when the project's generator list declares the ApiDocsGenerator)",
"docsMissing": "Declare `ApiDocsGenerator` in the generator list in codegen/Generators.cs if it is missing",
"apiSubDir": "api/csharp"
"verifyStep": "`dotnet meta verify --codegen` (the generated code and the requirements)"
}
5 changes: 1 addition & 4 deletions agent-context/servers/java.meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,5 @@
"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:generate",
"docsCondition": " (when the project's generator list declares the api-docs generator)",
"docsMissing": "Declare `com.metaobjects.generator.apidocs.JavaApiDocsGenerator` as a `<generator>` entry in the pom's `<generators>` if it is missing",
"apiSubDir": "api/java"
"verifyStep": "`mvn metaobjects:verify` (the generated code and the requirements)"
}
5 changes: 1 addition & 4 deletions agent-context/servers/kotlin.meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,5 @@
"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:generate",
"docsCondition": " (when the project's generator list declares the api-docs generator)",
"docsMissing": "Declare `com.metaobjects.generator.kotlin.apidocs.KotlinApiDocsGenerator` as a `<generator>` entry in the pom's `<generators>` if it is missing",
"apiSubDir": "api/kotlin"
"verifyStep": "`mvn metaobjects:verify` (the generated code and the requirements)"
}
5 changes: 1 addition & 4 deletions agent-context/servers/python.meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,5 @@
"displayName": "Python",
"install": "pip install metaobjects",
"codegenCommand": "metaobjects gen",
"docsCommand": "metaobjects gen",
"docsCondition": " (when a target's generator list declares `api-docs`)",
"docsMissing": "Declare `api-docs` in that target's `generators` in metaobjects.config.yaml if it is missing",
"apiSubDir": "api/python"
"verifyStep": "`metaobjects verify` (the generated code and the requirements; `--codegen` is its default)"
}
5 changes: 1 addition & 4 deletions agent-context/servers/typescript.meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,5 @@
"displayName": "TypeScript",
"install": "npm install -D @metaobjectsdev/cli @metaobjectsdev/codegen-ts",
"codegenCommand": "npx meta gen",
"docsCommand": "npx meta gen",
"docsCondition": "",
"docsMissing": "",
"apiSubDir": "api"
"verifyStep": "`npx meta verify --codegen` (the generated code and docs pages; the requirement gate runs on every `meta verify`)"
}
4 changes: 2 additions & 2 deletions agent-context/skills/metaobjects-authoring/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ This file covers what almost every model needs. The topics below live in
| `references/inheritance-tph.md` | several entities are variants of one thing sharing a single table (`@discriminator`) |
| `references/metadata-dependencies.md` | the project builds on another package's metadata (`dependencies`, cross-package `overlay`) |
| `references/reporting.md` | what a declared report gives you: what columns a report gets, time grains, null rules, rows with no facts (`@spine`), defaults (`@default`), engine differences |
| `references/requirements.md` | installed only when the project declares `requirement.*` nodes |
| `references/requirements.md` | you add, change or review a `requirement.*` node |

## The operating principle: model-first, generate-first

Expand Down Expand Up @@ -483,7 +483,7 @@ Every requirement must be **violable**: if you cannot say what breaking it looks

**A commit that adds, changes or removes behaviour updates the ledger in the same commit** (the new or changed claim, its `@status` and `@implementedBy`), or says in the commit message why it does not. `verify` checks that links resolve, not that the ledger is current.

If the project declares any `requirement.*` node, `references/requirements.md` is installed with the full authoring rules. If it does not and you are adding the first one, the shape is:
`references/requirements.md` has the full authoring rules. The shape of one node:

```yaml
- requirement.architectural:
Expand Down
1 change: 1 addition & 0 deletions agent-context/skills/metaobjects-codegen/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ exact config, generator names and commands for this project; read it. The other

| File | Open it when |
|---|---|
| `references/principles.md` | a rule in the always-on file does not settle the case: the full standing principles (adopting onto existing code, the schema and live database, prompts, requirements, owning and writing generators, physical names) with their reasons |
| `references/any-stack.md` | **the database, data store, HTTP framework or UI framework is not one a reference generator targets** — MySQL, MongoDB, DynamoDB, Express, NestJS, Next.js, Vue, … |
| `references/owning-generators.md` | generated output is wrong; your framework is not the one a reference emits for; you write or review a generator (the `own*()` accessor table) |
| `references/choosing-layers.md` | the generated API does not fit, you need joined or derived data, or you are adopting onto existing code |
Expand Down
Loading
Loading