Repository navigation
feat(cli): hand over every generator and drop the docs command - #439
Merged
Merged
Conversation
…equirements and agent-docs ejectable `meta eject <name>` used to copy a thin generator that decided what to emit and called the package to write it. It now also copies the transitive closure of the template modules the generator calls into `codegen/templates/`, the way it already copies the HTTP adapter, and the owned generator imports them from there. The engine (generator base, model walks, naming and type-mapping tables, projection and report lowering) stays in the package; `ENGINE_MODULES` lists it and the shared eject manifest's engine surface carries the same list. `requirements` and `agent-docs` get reference templates, are listed in `docs.generators`, and `meta docs` runs an owned copy in place of the packaged one. `meta gen` skips the packaged factory of either, as it does for `docsFile()`. Every one of the 24 ejectable generators is ejected alone into an empty project by a test derived from the catalog: nothing it holds imports a packaged emit module, it typechecks as an adopter's project does, and it writes what the packaged generator writes over six models. The TypeScript entries are gone from the manifest's pending list. The repository's own owned copies (the test-generators package and the examples) carry their template modules, written by scripts/sync-owned-template-copies.ts and held by a test. The release checklist's assess block now fails the deploy.
… docs` is removed ADR-0034 Amendment 9, the TypeScript half. Every page of documentation is an entry in `generators`, `meta gen` runs the list, `meta verify --codegen` checks it, and nothing is written that the list does not declare. - `meta docs` and `meta verify --docs` print the amendment's removal line and exit 2. A config with a `docs` block fails `meta gen` and `meta verify --codegen` before writing anything; `meta gen` with no metaobjects.config.ts fails with a pointer to the migration section. `meta init` writes no docs block. A config that declares no generator writes nothing, tool state included. - Docs factories write to the `docs` target and are refused by name when it is missing. New: `metamodelDocsFile()` (`metamodel-docs`, ejectable) and `docsSiteFile()` (`docs-site`); `meta eject docs-site` copies the site theme. The site prints no date, so its pages are checkable. The runner builds the model/api cross-link facts per target (`ctx.docs`) from `emitsModelDocs` / `emitsApiDocs`, and the agent schema on request. - `meta gen --generators <names>` narrows a run to declared entries and refuses others; a narrowed run reads run-level facts from the whole list. `meta gen` now passes the routes `expose` facts to the api reference, which it never did. - `meta verify --codegen` does not check documentation the repository git-ignores, says how many pages it skipped, and refuses a docs directory ignored whole (carried from `verify --docs`). - Owned generators and templates import the engine from the new `@metaobjectsdev/codegen-ts/engine` entry; zodEnumExpr, the primary-key and TPH walks moved into engine/template modules with forwarders where they were exported. - Removed from the package root: DocsConfig, ResolvedDocsConfig, DocsSurface, resolveDocsConfig. `apiDocsFile()` writes under `api/` by default. - Docs: the TypeScript section of docs-are-generators.md, CHANGELOG breaking notice and entries, ADR-0034 Amendment 9 TypeScript cells corrected, cli.md, ports/typescript.md, own-your-codegen.md, and the shipped agent context for all five ports. AGENTS.md no longer says 1.1.0 is released.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What Changed
meta docscommand and its docs-drift verify path. Docs now come from generator entries the config declares (docsFile,apiDocsFile,agentDocsFile,requirementsFile, docs-site).meta genemits only what the config lists.meta ejectcopies the full template closure of a TypeScript reference generator into the repo (server/typescript/packages/cli/src/lib/template-eject.ts), so the ejected copy owns the code that writes its output. Adds docs-site ejection and eject-contract and owned-copy tests.codegen-tsengine surface (engine.ts,engine-surface.ts,docs-run.ts,tph.ts,reference/requirements.ts,reference/agent-docs.ts), movestest-generatorssources undersrc/generators/, and updates the React/TanStack reference generators and the agent skill and context templates to the new generator model.Sequencing: the C# and Python half of ADR-0034 Amendment 9 (the sibling change) lands before rc.3 and the 1.1.0 cut, and nothing is released from
mainin between. The shipped agent context in this PR describes 1.1.0 as it will ship, all five ports included; theapi-docsnote infixtures/generator-registry-conformance/registry.jsondescribes the current tree, and the sibling change updates it.Validation runs: 1 no-mistakes run (review fixes folded into its rounds).
Net hand-written line change (vs
main, both commits): code +3,169 / −3,098 (net +71; 221 added lines are moved lines), tests +2,590 / −3,704 (net −1,114), docs +943 / −510 (net +433). Not hand-written, counted separately: owned template copies written byscripts/sync-owned-template-copies.ts+16,022 / −177, and regenerated fixtures and snapshots +510 / −430.Validation
Risk Assessment
Testing
Built the CLI and drove a disposable project end-to-end: eject of entity, docs and agent-docs generators, meta gen, and verify --codegen. Verify caught the ejected-generator behavior edit and the agent/schema.md drift, and passed the git-ignored-docs fresh-clone case with exit 0. Ran the TypeScript, C#, and Java registry and eject suites, all green. Python plan step and live skill evaluation were not run.
Pipeline
Updates from git push no-mistakes
✅ **Intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
docs/features/migrations/docs-are-generators.md:76- The TypeScript migration section says the 1.1 entries "write the same pages to the same paths", but it leaves out the first-run refusal every upgrading project will hit. 1.0meta docswrote pages with a rawwriteFileand never recorded them in.metaobjects/.gen-state/.hashes.json(old docs.ts:770/982). In 1.1 those pages go throughdecideAndWrite. An existing file with no hash record whose content differs from fresh output isno-snapshot-refused(overwrite-policy.ts:541-558). This change itself alters the bytes of two page sets: every metamodel page's header (REGEN_COMMANDin metadata/src/metamodel-docs/render.ts:27, visible in all 19 fixtures/metamodel-docs and site-reference files) and every docs-site page's footer (the date stamp is now ""). Concrete sequence: a 1.0 project that committed docs/generated (with --site) and docs/metamodel follows this section and runsmeta gen. Every site page and every metamodel page is refused with a per-file warning.meta verify --codegenthen reports each as~drift, because there is no recorded hash and the check fails closed. Nothing in the guide tells the agent how to get out of this. Fix: add an explicit step to the section, "delete the 1.0 docs output directories before the firstmeta gen", or runmeta gen --generators <the docs names> --baseline=fresh. The--generatorsnarrowing keeps the fresh baseline off code files. Also soften the "same pages" sentence at line 76.server/typescript/packages/codegen-ts/src/runner.ts:756- A 1.0 owneddocsorapi-docscopy, moved intogeneratorsas the guide says (docs-are-generators.md:142 and :169-171, 'the owned copy, ingenerators, like any other owned copy'), breaks the new rule that documentation is never written into the code's output directory by default. The 1.0 references (base reference/docs.ts:80-94 and reference/api-docs.ts:61-75) set notarget, carrydocsSurface, and readctx.docsDoor, which no longer exists. The runner used to skip adocsSurfacegenerator with a warning. It now runs it on the default target:meta genwrites README.md and the model pages into the codeoutDir(for example src/generated), and the api pages undersrc/generated/docs/api, with no cross-links. It does this silently.meta eject docswithout--forcekeeps the old copy and only prints a DIFFERS note. Fix at the earliest shared boundary: in runGen, before the generator loop, refuse any declared generator that still carries the obsoletedocsSurfaceproperty, and namemeta eject <name> --forceas the remedy. That coversmeta gen,verify --codegenand programmatic callers alike, just as the legacydocsblock is refused. Also change the guide's 'A generator you own' paragraph to say a 1.0 copy must be re-ejected, not moved.server/typescript/packages/cli/src/lib/catalog-listing.ts:226-meta gen --list --proberuns each generator throughrunGenwithout the run inputs thatmeta gennow supplies to the new documentation generators.probeOne'srunGencall (catalog-listing.ts:226-235) receives neithersourceRootsnoragentSchema, and theprobeoption assembled in gen.ts:510 carries only metadata, scope and sourceFiles. Result 1: the newdocs-siterow reports a probe failure on every project.docsSiteFile()throws 'the run named no metadata source directories (ctx.sourceRoots)' (docs-site-file.ts:53-59), and the docs-target retry does not cure it. Result 2: theagent-docscount always leaves outagent/schema.md, becausectx.docs.agentSchemais undefined. Both understate whatmeta genwould emit. Fix: threadsourceRoots: sourceRootsOf(genCollection)and the samebuildAgentSchemaInputthunk throughCatalogListingOpts.probeintoprobeOne, as gen.ts:244-251 does.agent-context/templates/always-on.md.mustache:62- The shipped agent context now describes the C# and Python halves of Amendment 9 as done, but this tree does not implement them. The skill text says there is "no separate docs command or docs config block on any port", thatcodegen/Generators.csis "scaffolded bydotnet meta init", and that--generators(TypeScript, C#, Python) only narrows a declared list. The same claims appear in agent-context/servers/csharp.meta.json and python.meta.json (docsCommanddotnet meta gen/metaobjects gen, 'DeclareApiDocsGeneratorin codegen/Generators.cs'), skills/metaobjects-codegen/references/csharp.md ("There is nodotnet meta docscommand (removed in 1.1.0)"), references/owning-generators.md, audit/references/csharp.md, and AGENTS.md ('documentation a set of generators in every port … the docs commands are removed'). In this tree, C# still dispatches"docs" => RunDocs(server/csharp/MetaObjects.Cli/Program.cs:75) and noGenerators.csexists anywhere under server/csharp. Python still has thedocssubcommand (server/python/src/metaobjects/cli.py:2773), which readsdocs.generators. This change's own registry.json note forapi-docssays 'C# and Python still run it from the port's docs command … and their gen commands skip it'. A C# or Python adopter who follows the shipped agent context gets told to use a file and behaviour that do not exist. Decide the sequencing: either the C# and Python Amendment 9 changes must land before 1.1.0 is cut (and this PR depends on them), or the C#/Python wording here should describe the current state until they land.server/typescript/packages/test-generators/src/index.ts:9- Stale pointer. The comment says the copies are byte-gated againstreadReferenceTemplate()bytest/owned-copies-current.test.ts. This change deleted that test from test-generators. The gate is now server/typescript/packages/cli/test/owned-copies-current.test.ts, and it compares against the eject closure (generator plustemplates/), notreadReferenceTemplate(). Update the comment to name the new location and the new comparison.🔧 Fix applied.
3 warnings still open:
agent-context/templates/always-on.md.mustache:62- The shipped agent context now describes the C# and Python halves of Amendment 9 as done, but this tree does not implement them. The skill text says there is "no separate docs command or docs config block on any port", thatcodegen/Generators.csis "scaffolded bydotnet meta init", and that--generators(TypeScript, C#, Python) only narrows a declared list. The same claims appear in agent-context/servers/csharp.meta.json and python.meta.json (docsCommanddotnet meta gen/metaobjects gen, 'DeclareApiDocsGeneratorin codegen/Generators.cs'), skills/metaobjects-codegen/references/csharp.md ("There is nodotnet meta docscommand (removed in 1.1.0)"), references/owning-generators.md, audit/references/csharp.md, and AGENTS.md ('documentation a set of generators in every port … the docs commands are removed'). In this tree, C# still dispatches"docs" => RunDocs(server/csharp/MetaObjects.Cli/Program.cs:75) and noGenerators.csexists anywhere under server/csharp. Python still has thedocssubcommand (server/python/src/metaobjects/cli.py:2773), which readsdocs.generators. This change's own registry.json note forapi-docssays 'C# and Python still run it from the port's docs command … and their gen commands skip it'. A C# or Python adopter who follows the shipped agent context gets told to use a file and behaviour that do not exist. Decide the sequencing: either the C# and Python Amendment 9 changes must land before 1.1.0 is cut (and this PR depends on them), or the C#/Python wording here should describe the current state until they land.server/typescript/packages/cli/src/lib/codegen-drift.ts:299-meta verify --codegennow checks documentation pages, so a project that generates docs but does not commit them fails the gate. Whengeneratorslists a docs generator and git ignores the whole docs output directory,computeCodegenDriftreturns a harderror(exit 2): 'the repository git-ignores every one of them, so there is nothing to compare'. The testgen-docs-generators.test.ts:305-311asserts this exit 2. In 1.0 the same refusal existed only behind the opt-inmeta verify --docs, andverify --codegennever looked at documentation. Concrete sequence: a 1.0 project runsmeta docslocally withdocs/generated/in .gitignore, and its CI runsmeta verify --codegen. It follows docs-are-generators.md and moves its docs intogeneratorswithtargets.docs. Its CI then exits 2 on every run. The guide's 'Things that are different' and 'Scripts and CI' sections do not mention this. The error text offers only two remedies: commit the pages, or stop generating docs. No option lets a project keep generating docs locally without committing them and still passverify --codegen. This is a product decision. Options: (a) treat a docs directory that is ignored as a whole as 'not checked' and print the count line already used for partly ignored directories, without failing; (b) keep the refusal and document it in the migration section, with the exact way out; (c) add a narrowing option. The remedy changes gate behaviour, so it needs your decision.docs/features/own-your-codegen.md:639- The TypeScript row of the per-port 'own your codegen' table still says "docs,api-docs,requirementsandagent-docsare run bymeta docs, which runs a copy listed indocs: { generators: [...] }". This change removesmeta docsand thedocsblock for TypeScript. Section 224-260 of the same file and docs-are-generators.md now say these generators are listed ingeneratorsand run bymeta gen. An agent or adopter who reads this table is sent to a command that exits with the removal message, and to a config block thatmeta genrefuses (legacyDocsConfigMessage). Fix: replace the sentence with the 1.1 wiring. The docs generators,metamodel-docsanddocs-siteincluded, are entries ingeneratorsthat write to thedocstarget and are run bymeta gen. Keep the existing link to #the-docs-generators-and-shared-model-typescript. The C# rows at 1435-1462 describedotnet meta docs, which still exists in this tree. Leave them as they are, per the review-4 decision.🔧 Fix applied.
2 warnings still open:
agent-context/templates/always-on.md.mustache:62- The shipped agent context now describes the C# and Python halves of Amendment 9 as done, but this tree does not implement them. The skill text says there is "no separate docs command or docs config block on any port", thatcodegen/Generators.csis "scaffolded bydotnet meta init", and that--generators(TypeScript, C#, Python) only narrows a declared list. The same claims appear in agent-context/servers/csharp.meta.json and python.meta.json (docsCommanddotnet meta gen/metaobjects gen, 'DeclareApiDocsGeneratorin codegen/Generators.cs'), skills/metaobjects-codegen/references/csharp.md ("There is nodotnet meta docscommand (removed in 1.1.0)"), references/owning-generators.md, audit/references/csharp.md, and AGENTS.md ('documentation a set of generators in every port … the docs commands are removed'). In this tree, C# still dispatches"docs" => RunDocs(server/csharp/MetaObjects.Cli/Program.cs:75) and noGenerators.csexists anywhere under server/csharp. Python still has thedocssubcommand (server/python/src/metaobjects/cli.py:2773), which readsdocs.generators. This change's own registry.json note forapi-docssays 'C# and Python still run it from the port's docs command … and their gen commands skip it'. A C# or Python adopter who follows the shipped agent context gets told to use a file and behaviour that do not exist. Decide the sequencing: either the C# and Python Amendment 9 changes must land before 1.1.0 is cut (and this PR depends on them), or the C#/Python wording here should describe the current state until they land.agent-context/skills/metaobjects-codegen/references/typescript-docs.md:68- The TypeScript docs skill tells an agent to read./docs/api/AGENT-API.mdbefore it calls generated code. In 1.1.0 that path does not exist for the configuration the same file recommends. The file's own example (line 36) setstargets: { docs: { outDir: "./docs/generated" } }, andapiDocsFile()writes underapi/in that target (DEFAULT_API_DIR = "api", target "docs"). The page therefore lands at./docs/generated/api/AGENT-API.md, or more generally at<targets.docs.outDir>/api/AGENT-API.md. An agent that follows the skill looks in the wrong place, finds nothing, and either guesses the generated API or regenerates without need. The always-on template avoids this: it names the page relative to the docs target ({{apiSubDir}}/AGENT-API.mdundertargets.docs.outDir). The wrong path predates this change, but this change rewrote the file around thedocstarget, so the file now contradicts itself. The user named the skill revisions as a priority. Fix: say<targets.docs.outDir>/api/AGENT-API.md(e.g../docs/generated/api/AGENT-API.md). Same defect at line 10 of the same file (the Contents bullet). After the edit, regenerate the byte-identical fixture copies: fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-codegen/references/typescript-docs.md and fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-codegen/references/typescript-docs.md.🔧 Fix applied.
3 warnings still open:
agent-context/templates/always-on.md.mustache:62- The shipped agent context now describes the C# and Python halves of Amendment 9 as done, but this tree does not implement them. The skill text says there is "no separate docs command or docs config block on any port", thatcodegen/Generators.csis "scaffolded bydotnet meta init", and that--generators(TypeScript, C#, Python) only narrows a declared list. The same claims appear in agent-context/servers/csharp.meta.json and python.meta.json (docsCommanddotnet meta gen/metaobjects gen, 'DeclareApiDocsGeneratorin codegen/Generators.cs'), skills/metaobjects-codegen/references/csharp.md ("There is nodotnet meta docscommand (removed in 1.1.0)"), references/owning-generators.md, audit/references/csharp.md, and AGENTS.md ('documentation a set of generators in every port … the docs commands are removed'). In this tree, C# still dispatches"docs" => RunDocs(server/csharp/MetaObjects.Cli/Program.cs:75) and noGenerators.csexists anywhere under server/csharp. Python still has thedocssubcommand (server/python/src/metaobjects/cli.py:2773), which readsdocs.generators. This change's own registry.json note forapi-docssays 'C# and Python still run it from the port's docs command … and their gen commands skip it'. A C# or Python adopter who follows the shipped agent context gets told to use a file and behaviour that do not exist. Decide the sequencing: either the C# and Python Amendment 9 changes must land before 1.1.0 is cut (and this PR depends on them), or the C#/Python wording here should describe the current state until they land.docs/features/own-your-codegen.md:361- This change emptieseject.pendingin fixtures/generator-registry-conformance/registry.json (it is now[]). The CHANGELOG 1.1.0 entry records that closure. The section 'Whatmeta ejecthands over, and what stays core (TypeScript)' was not updated and still says: "It is not yet true of all of them: several owned copies still call emit code in the package, andfixtures/generator-registry-conformance/registry.jsonlists each one undereject.pendinguntil it is closed. What follows is the part that is already handed over." For TypeScript this is now false. A reader, or an agent fed llms-full.txt, will conclude that the Amendment 8 hand-over is still incomplete and will look for a pending list that is empty. Fix: replace the sentence with the current state. Every ejectable TypeScript generator hands over its template-module closure intocodegen/templates/, and only the engine (ENGINE_MODULES, imported from@metaobjectsdev/codegen-ts/engine) stays packaged. Then regenerate docs/llms/llms-full.txt if it embeds this page.agent-context/skills/metaobjects-codegen/references/typescript.md:129- This change rewrote this paragraph of the shipped TypeScript codegen skill. It now says "One entry cannot be ejected and ispackage-onlyinmeta gen --list: thetemplateprimitive". That count is wrong.docs-siteis also not ejectable: it is absent from REFERENCE_GENERATOR_NAMES in reference-templates.ts, soejectable("docs-site")is false (generator-registry.ts:347). Its registry note says the builder stays packaged andmeta eject docs-sitecopies only the site's templates and assets. docs/features/own-your-codegen.md and docs/features/cli.md both say two entries (templateanddocs-site) arepackage-only. A second wrong sentence sits in the same paragraph: "The engine primitives come from the package main entry,@metaobjectsdev/codegen-ts". An ejected copy now imports the engine from@metaobjectsdev/codegen-ts/engine(template-eject.ts ENGINE_ENTRY; every reference under src/reference imports that entry). Fix: name bothpackage-onlyentries, and say that owned copies import the engine from@metaobjectsdev/codegen-ts/engine. Then regenerate the byte-identical fixture copies with the sdk regen script: fixtures/agent-context-conformance/ts-react-tanstack/expected/.claude/skills/metaobjects-codegen/references/typescript.md and fixtures/agent-context-conformance/ts-requirements/expected/.claude/skills/metaobjects-codegen/references/typescript.md.🔧 Fix applied.
2 warnings still open:
agent-context/templates/always-on.md.mustache:62- The shipped agent context now describes the C# and Python halves of Amendment 9 as done, but this tree does not implement them. The skill text says there is "no separate docs command or docs config block on any port", thatcodegen/Generators.csis "scaffolded bydotnet meta init", and that--generators(TypeScript, C#, Python) only narrows a declared list. The same claims appear in agent-context/servers/csharp.meta.json and python.meta.json (docsCommanddotnet meta gen/metaobjects gen, 'DeclareApiDocsGeneratorin codegen/Generators.cs'), skills/metaobjects-codegen/references/csharp.md ("There is nodotnet meta docscommand (removed in 1.1.0)"), references/owning-generators.md, audit/references/csharp.md, and AGENTS.md ('documentation a set of generators in every port … the docs commands are removed'). In this tree, C# still dispatches"docs" => RunDocs(server/csharp/MetaObjects.Cli/Program.cs:75) and noGenerators.csexists anywhere under server/csharp. Python still has thedocssubcommand (server/python/src/metaobjects/cli.py:2773), which readsdocs.generators. This change's own registry.json note forapi-docssays 'C# and Python still run it from the port's docs command … and their gen commands skip it'. A C# or Python adopter who follows the shipped agent context gets told to use a file and behaviour that do not exist. Decide the sequencing: either the C# and Python Amendment 9 changes must land before 1.1.0 is cut (and this PR depends on them), or the C#/Python wording here should describe the current state until they land.AGENTS.md:9- Round 4's fix for review-8 corrected the TypeScript package-only count in own-your-codegen.md, the CHANGELOG and the skill copies, but missed two sibling sites. (1) AGENTS.md:9 still says "meta gen --listmarks the ones that do notpackage-only(in TypeScript:template, which is exempt for good, andrequirementsandagent-docs, which are pending ...)". This change maderequirementsandagent-docsejectable: both are in REFERENCE_GENERATOR_NAMES, and registry.jsoneject.pendingis[]. The only package-only TypeScript entries are nowtemplateanddocs-site, as eject-templates-contract.test.ts:82 asserts. AGENTS.md is loaded into every agent session, so this false statement reaches every future session. (2) server/typescript/packages/codegen-ts/src/generators/index.ts:17, rewritten in this change, says "today that istemplatealone", and the next sentence says the docsSiteFile builder stays packaged, so the comment contradicts itself. Fix both to nametemplate(the Mustache primitive) anddocs-site(its builder stays packaged;meta eject docs-sitecopies the theme), and to drop the 'pending' wording. The AGENTS.md edit is a fix to memory-file content that is part of this change. Separately, CHANGELOG.md:218 says the contract test ejects "each of the 24 generators", but the composed catalog has 25 ejectable names (21 core, 1 react, 3 tanstack). Check that number while making these edits.🔧 Fix applied.
4 issues (3 warnings, 1 info) still open:
agent-context/templates/always-on.md.mustache:62- The shipped agent context now describes the C# and Python halves of Amendment 9 as done, but this tree does not implement them. The skill text says there is "no separate docs command or docs config block on any port", thatcodegen/Generators.csis "scaffolded bydotnet meta init", and that--generators(TypeScript, C#, Python) only narrows a declared list. The same claims appear in agent-context/servers/csharp.meta.json and python.meta.json (docsCommanddotnet meta gen/metaobjects gen, 'DeclareApiDocsGeneratorin codegen/Generators.cs'), skills/metaobjects-codegen/references/csharp.md ("There is nodotnet meta docscommand (removed in 1.1.0)"), references/owning-generators.md, audit/references/csharp.md, and AGENTS.md ('documentation a set of generators in every port … the docs commands are removed'). In this tree, C# still dispatches"docs" => RunDocs(server/csharp/MetaObjects.Cli/Program.cs:75) and noGenerators.csexists anywhere under server/csharp. Python still has thedocssubcommand (server/python/src/metaobjects/cli.py:2773), which readsdocs.generators. This change's own registry.json note forapi-docssays 'C# and Python still run it from the port's docs command … and their gen commands skip it'. A C# or Python adopter who follows the shipped agent context gets told to use a file and behaviour that do not exist. Decide the sequencing: either the C# and Python Amendment 9 changes must land before 1.1.0 is cut (and this PR depends on them), or the C#/Python wording here should describe the current state until they land.server/typescript/packages/codegen-ts/src/generators/docs-file.ts:118- Two places this change added say the model pages followmeta gen's scope. CHANGELOG.md:936 says: "The model pages followmeta gen'sscopeand entity selection, as every per-object generator does". server/typescript/packages/cli/README.md:358 says the model pages (docsFile()) follow the scope. The code does not do this. docsFile() builds its pages fromctx.loadedRoot.objects().filter(ctx.matches)(docs-file.ts:118-120). runner.ts:804 setsmatches: (e) => generator.filter?.(e) ?? true, which reads only the generator's ownfilterand never readsscopeor themeta gen <Entity>selection. Onlyctx.entitiesandctx.selectcarry the scope. Concrete case: a project whose config hasscope: { include: ["app::core::**"] }and declares docsFile().meta genwrites a model page and an index entry for every object in the collection, including objects outside app::core. The CHANGELOG and README tell the user these pages are scoped, and no error appears.meta verify --codegenregenerates the same way, so no drift is reported either. This needs a product decision. Either correct both texts to say the model pages document the whole loaded model, like the other docs generators, or make docsFile() honour the scope (filter byctx.selectand the entity selection, or walkctx.entities). The second option changes the pages written for scoped projects.server/typescript/packages/cli/test/gen-docs-generators.test.ts:283- This change deleted cli/test/integration/verify-docs-drift.test.ts. That test ran the drift gate end to end against examples/showcase with a real migrate-ts expected-schema snapshot. It was the only test that checked agent/schema.md that way, and it showed the gate failing in three distinct ways. The replacement case at gen-docs-generators.test.ts:283-296 uses a synthetic one-entity fixture. It wires only docsFile() and never wires agentDocsFile(), so it never reads a migrate-ts schema. examples/showcase/metaobjects.config.ts declares no docs generator, so showcase-drift.test.ts does not cover this either. Observable failure that no test now catches: a project wires agentDocsFile() and runsmeta gen, then changes a column in its metadata without regenerating. Ifmeta verify --codegenthen fails to report agent/schema.md as drifted, the suite stays green. Independent oracle: agent/schema.md is generated from the expected schema, so a changed column must change its bytes, and the gate must exit non-zero and name that file. Fix: add an integration case that wires agentDocsFile() on a project with a persisted entity, runsmeta gen, changes a column, and asserts thatmeta verify --codegenfails and names agent/schema.md. A related loss: the deleted integration/eject-docs-tier.test.ts ran the built CLI to check that an edited, ejected docs generator is reported as drift. The replacement at gen-docs-generators.test.ts:325-345 runs in-process and checks only that an unedited ejected copy writes the same output. verify-codegen-ejected-generator.test.ts still covers the generic edit-is-drift mechanism.server/typescript/packages/codegen-ts/src/generator-registry.ts:290- This change added theoptionsstring "subDir?, modelBaseUrl?, filter?, target?" to theapi-docscatalog entry. It omitsmodelSurface?, which ApiDocsFileOpts declares (api-docs-file.ts:65). Under Amendment 9,modelSurfaceis the explicit override for the new default, which comes fromctx.docs.modelPages(api-docs-file.ts:81).meta gen --listprints this string. An agent that reads the catalog to discover apiDocsFile()'s options is told about four of the five and does not learn of this override. Fix: addmodelSurface?to the options string.🔧 Fix applied.
2 warnings still open:
agent-context/templates/always-on.md.mustache:62- The shipped agent context now describes the C# and Python halves of Amendment 9 as done, but this tree does not implement them. The skill text says there is "no separate docs command or docs config block on any port", thatcodegen/Generators.csis "scaffolded bydotnet meta init", and that--generators(TypeScript, C#, Python) only narrows a declared list. The same claims appear in agent-context/servers/csharp.meta.json and python.meta.json (docsCommanddotnet meta gen/metaobjects gen, 'DeclareApiDocsGeneratorin codegen/Generators.cs'), skills/metaobjects-codegen/references/csharp.md ("There is nodotnet meta docscommand (removed in 1.1.0)"), references/owning-generators.md, audit/references/csharp.md, and AGENTS.md ('documentation a set of generators in every port … the docs commands are removed'). In this tree, C# still dispatches"docs" => RunDocs(server/csharp/MetaObjects.Cli/Program.cs:75) and noGenerators.csexists anywhere under server/csharp. Python still has thedocssubcommand (server/python/src/metaobjects/cli.py:2773), which readsdocs.generators. This change's own registry.json note forapi-docssays 'C# and Python still run it from the port's docs command … and their gen commands skip it'. A C# or Python adopter who follows the shipped agent context gets told to use a file and behaviour that do not exist. Decide the sequencing: either the C# and Python Amendment 9 changes must land before 1.1.0 is cut (and this PR depends on them), or the C#/Python wording here should describe the current state until they land.server/typescript/packages/cli/src/lib/codegen-drift.ts:295-verify --codegenfails on a fresh clone of a project that git-ignores its whole docs directory. Prior fix round 5d154e8 ("Skip git-ignored docs dirs in verify") introduced this code. It asks git about ignored pages withgitIgnored(committed, …), andgitIgnoredrunsgit -C <committed> check-ignore(git-ignore.ts:69).committedOutDirs(codegen-drift.ts:131) returns every declared outDir, including ones that do not exist on disk. Failing sequence: a project listsdocsFile()withtargets.docs.outDir: "./docs/generated"and hasdocs/in .gitignore, so it commits no pages. A CI runner clones the repository, so docs/generated is absent.listFiles(committed)returns [], the fresh run emits pages, andall.size > 0callsgitIgnored.git -C <missing dir>fails with "cannot change to" (exit 128), so the lookup returnsunavailableandignoredstays empty. The run then skips the docsIgnoredDirs branch, reports every page as+ … (regen would emit it; not committed), and exits 1. The same project passes on the developer's machine, wheremeta gencreated the directory. The code comment at lines 287-292 and the docsIgnoredDirs doc both promise the opposite: a verdict that "is a property of the repository and not of the machine", and "a project that generates its documentation without committing it passes". The existing test (gen-docs-generators.test.ts:321, "a docs directory the repository ignores whole") runsmeta genfirst, so the directory exists and the test cannot catch this. Fix: run the lookup from the project root, which always exists, and pass root-relative paths (relative(root, join(committed, rel))). Then map the results back to the dir-relative keys thatignored.has(toPosix(rel))checks. Add a case that deletes docs/generated aftermeta genand expectsverify --codegento exit 0 and name the ignored directory.🔧 Fix applied.
2 issues (1 warning, 1 info) still open:
agent-context/templates/always-on.md.mustache:62- The shipped agent context now describes the C# and Python halves of Amendment 9 as done, but this tree does not implement them. The skill text says there is "no separate docs command or docs config block on any port", thatcodegen/Generators.csis "scaffolded bydotnet meta init", and that--generators(TypeScript, C#, Python) only narrows a declared list. The same claims appear in agent-context/servers/csharp.meta.json and python.meta.json (docsCommanddotnet meta gen/metaobjects gen, 'DeclareApiDocsGeneratorin codegen/Generators.cs'), skills/metaobjects-codegen/references/csharp.md ("There is nodotnet meta docscommand (removed in 1.1.0)"), references/owning-generators.md, audit/references/csharp.md, and AGENTS.md ('documentation a set of generators in every port … the docs commands are removed'). In this tree, C# still dispatches"docs" => RunDocs(server/csharp/MetaObjects.Cli/Program.cs:75) and noGenerators.csexists anywhere under server/csharp. Python still has thedocssubcommand (server/python/src/metaobjects/cli.py:2773), which readsdocs.generators. This change's own registry.json note forapi-docssays 'C# and Python still run it from the port's docs command … and their gen commands skip it'. A C# or Python adopter who follows the shipped agent context gets told to use a file and behaviour that do not exist. Decide the sequencing: either the C# and Python Amendment 9 changes must land before 1.1.0 is cut (and this PR depends on them), or the C#/Python wording here should describe the current state until they land.server/typescript/packages/codegen-ts/test/agent-ui-page-parity.test.ts:358- This branch changed the parity test. It no longer runsagentDocsFile()throughrunGen: the generator was taken out of thegeneratorsarray and is now called directly with a context the test builds by hand (includeUiTier: runEmitsUiTier(suite)and amakeRenderContext). The comment added at lines 358-361 justifies this with "the runner skips a docs generator, so it is generated the way that door does …meta docs… cli/src/commands/docs.ts". After this change none of that is true. The runner runs docs generators (ADR-0034 Amendment 9), andcli/src/commands/docs.tsis now a two-line stub that exits 2. The comment tells the next reader the opposite of how the system works. The test also checks the agent page against a context it built itself, not against the onerunGenbuilds (ctx.config.includeUiTier,renderContext.apiPrefix). Its parity claim ("whatmeta genwould have written") therefore no longer covers the agent page. gen-docs-generators.test.ts:214 partly covers apiPrefix throughmeta gen. Fix: putagentDocsFile()back insuite, addtargets: { docs: { outDir } }(or passtarget), readagent/ui.mdfrom the runner's output, and delete the hand-built context and the stale comment.✅ **Test** - passed
✅ No issues found.
scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchainsbun run buildin server/typescript/packages/climeta eject --listandmeta gen --listagainst built CLI: 25 TS generators available, own 0Disposable project /tmp/nm-eject-proj:meta init,meta eject entity docs agent-docs,meta gen,meta verify --codegenAdversarial: behavior edit to ejected entity generator (adds Marker.ts) -> verify exit 1 naming src/generated/Marker.ts; restored -> exit 0Adversarial: changed @maxLength with no regen -> verify exit 1 naming docs/generated/agent/schema.mdFresh-clone case: docs/ git-ignored, docs dir deleted -> verify exit 0 with not-compared messagecd server/typescript/packages/sdk && bun test(333 pass)cd server/typescript/packages/docs-site && bun test(56 pass)cd server/typescript/packages/cli && bun test(1702 tests, 0 fail)cd server/typescript/packages/codegen-ts && bun test(2645 pass, 0 fail)cd server/csharp && dotnet test MetaObjects.Codegen.Tests --filter "FullyQualifiedName~GeneratorRegistry|FullyQualifiedName~EjectContract"(32 pass)cd server/java && mvn -o -pl codegen-spring,codegen-kotlin,maven-plugin -am test -Dtest='GeneratorRegistryConformanceTest,EjectContractTest'(surefire: 27 tests, 0 failures)Not run: plan step 6 Python pytest (no server/python/.venv present)Not run: skill revisions via application-building agent tests (LLM spend, needs approval)✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.