Repository navigation
feat: assistant-neutral agent context and per-language docs truth pass - #569
Merged
Merged
Conversation
…ts, assistant-neutral agent file Docs truth pass (1.3.0 plan PR 8): - Every port page and the README getting-started path now say that schema migrations and database checks run in the Node `meta` tool. - New docs/features/language-differences.md: one table of what differs by port (list default and cap, validation body, filter errors, field naming, data access, migrations, hand edits), linked from the port pages. - Docs that still described .metaobjects/CLAUDE.md are corrected. Assistant-neutral agent context (1.3.0 plan PR 36): - `meta init --skills-dir <dir>` / `meta agent-docs --skills-dir` installs skills for any assistant (e.g. .agents/skills); the choice is recorded in the manifest and kept on refresh, and old copies are pruned on a move. - The duplicate .metaobjects/CLAUDE.md is no longer written (pruned on refresh); root wiring creates AGENTS.md and CLAUDE.md importing .metaobjects/AGENTS.md. - The always-on text gains a "Calling the generated REST API" block (filter[f][op]=v, operators, sort, paging, error shapes) and drops stack-specific catalogs in favour of skill pointers. - Staleness nudges in C#, Java and Python use the neutral wording.
…CLAUDE.md exists; refresh advises
… api-contract default-page contradiction
Resolve CHANGELOG.md (keep both [Unreleased] entries; always-on sizes updated to the final measured values) and cli README (keep the assistant-neutral init description and main's outputLayout sentence).
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 init --skills-dir <dir>(andmeta agent-docs --skills-dir <dir>) installs themetaobjects-*skills where another assistant reads them (default stays.claude/skills, e.g..agents/skills); the choice is recorded in.metaobjects/.agent-context.jsonso refreshes keep it, moving the directory prunes untouched copies at the old one, and absolute or..paths are refused. The duplicate.metaobjects/CLAUDE.mdis no longer written — a refresh removes an untouched copy and names a hand-edited one — and first init on a repo with only a rootCLAUDE.mdalso creates rootAGENTS.md(a refresh only prints an advisory). The five agent-context conformance stacks and their sdk/cli tests are regenerated to match..metaobjects/AGENTS.mdgains a "Calling the generated REST API" block — the filter form?filter[<field>][<op>]=<value>(never?status=active) with the nine operators, sort/limit/offset including each port's default whenlimitis omitted, and the{"error": ...}bodies — while the Java/Kotlin generator class lists, the TypeScript catalog pipeline and the prompt/report rules move behind the skills they pointed to; root wiring adds a plain pointer sentence beside the@import, and the C#/Java/Python staleness notices no longer name.claude/skills.docs/features/language-differences.mdlists what the same model does differently per port — schema migrations and database checks need the Nodemetatool in every language, list default and cap, validation and filter error bodies, TypeScript-only filter extras, field names in code, generated data access, hand-edit handling — and the README, port pages,api-contract,cliand llms docs now say up front that Java/Kotlin/C#/Python teams still run Node for schema work and link to the page.Always-on agent file size, before and after
The always-on file is
.metaobjects/AGENTS.md, the text every agent session loads.mainbefore this PRAGENTS.md+ duplicateCLAUDE.mdAGENTS.md+ duplicateCLAUDE.mdAGENTS.mdonlymain, which had already shed most of the Java, Flyway and prompt detail, it grows up to 12% (Java+Kotlin shrinks slightly), because the new "Calling the generated REST API" block (filter syntax and operators, sort, paging, error shapes) is larger than the stack-specific catalogs that moved behind skills. Bytes on disk are down 44-50% because the duplicate is gone.Also
Validation
Risk Assessment
✅ Low: The round-1 fixes (REST-block wording, Kotlin in the Schema heading, regenerated fixtures) check out against source, and the new assistant-neutral skills-install, duplicate-file removal and docs changes are well bounded and covered by behavioural tests.
Testing
The configured baseline (ts-fast + ts-unit, including the new init-agent-context tests and agent-context conformance fixtures) passed before this step; this step added the ts-slow integration lane (LOCAL CI PASSED) and drove eleven scenarios live. Init wiring: fresh init creates root AGENTS.md and CLAUDE.md with the pointer+@import block and only .metaobjects/AGENTS.md (5,960 bytes vs 17,924 in 1.2.0, Flyway moved behind the codegen skill); first init on a CLAUDE.md-only repo creates root AGENTS.md and preserves hand-written content; refresh on such a repo creates no root file and prints exactly one advisory; an AGENTS.md-only repo stays unchanged; --skills-dir installs, is remembered on refresh, moves with old files pruned, and refuses absolute/.. paths with exit 2. A real 1.2.0 project (npx @metaobjectsdev/cli@1.2.0) upgraded cleanly: untouched legacy .metaobjects/CLAUDE.md removed with root CLAUDE.md byte-identical, hand-edited legacy kept and named. REST-conventions claims hold on the real Fastify mount: no limit returns 60 rows (not a hidden page of 50), limit honored, bare ?field= gives 400 filter.bare_field naming the bracketed form, all nine operators plus sort/offset/withCount driven. "Migrations/DB checks need Node" is true at the product level: Python's metaobjects CLI has no migrate and refuses verify --db pointing at Node, dotnet meta lists no migrate and documents --db as unsupported. Hand-edit overwrite verified via the ports' own sweep tests (C# 14/14, Java 18+26). Evidence logs live in the evidence dir (index: this-round-index.md); the worktree was left clean, the throwaway test deleted, and build outputs removed. One cosmetic note recorded (empty dir husks after a skills move).
meta init --server typescriptin an empty disposable project is assistant-neutral: root AGENTS.md AND CLAUDE.md created each carrying the pointer line + @.metaobjects/AGENTS.md import, only .m…metaobjects --help(py3.11 venv) lists gen/verify/fmt/eject/init/deps with no migrate, andmetaobjects verify --db sqlite:///demo.dbrefuses…Evidence: Evidence index for this round (scenario → result → artifact map)
Evidence: S1/S3/S5: init + skills-dir drive transcripts (fresh init verify, refresh advisory, move+prune+refusals)
Evidence: S6/S7: 1.2.0→this-branch upgrade, case A (legacy removed, root md5 identical) and case B (hand-edited legacy kept + named)
Evidence: S8: 60-row no-limit live HTTP check (every row > 50 default; limit=50 honored)
2 pass / 0 fail — GET /subscribers without ?limit returned all 60 seeded rows; ?limit=50 returned 50Evidence: S8: full REST-conventions test run on the real Fastify mount (filter ops, bare-field 400, sort, 405s)
82 pass / 0 fail / 204 expect() across 3 filesEvidence: S9: Python port CLI help (no migrate; Node owns schema) and live verify --db refusal
error: verify --db is not supported in the Python port; schema verify is the migrate engine (the NodemetaCLI, ADR-0015).Evidence: S9/S10: dotnet meta --help (no migrate; --db NOT supported) + C# AgentContextStalenessTests 14/14
Evidence: S10: C# OrphanSweepTests (hand-edit overwrite) 14/14
Evidence: S11: ts-slow integration lane — LOCAL CI PASSED, rc=0
Evidence: S1: the always-on REST-conventions block as generated (corrected per-port wording)
Pipeline
Updates from git push no-mistakes
✅ **Intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
agent-context/templates/always-on.md.mustache:46- The new REST-conventions block states a bare?status=activeis refused by TypeScript and 'the other ports ignore it and return every row'. Verified against source: only C# returns every row (RoutesGenerator.cs:163 leaves limit null); Java, Kotlin and Python return their default page of 50 (SpringControllerGenerator.java:838limit != null ? limit : 50; KotlinSpringControllerGenerator.kt:74; python router_generator.py:19 limit=50). The sentence contradicts the block's own limit bullet two lines later ('without it TypeScript and C# return every row, the other ports 50') and the new language-differences table, where only the C# cell says 'every row comes back'. An agent on a Java/Kotlin/Python project is told to expect the full result set. Fix: drop 'and return every row' (the per-port default is already stated by the limit bullet). Sibling sites carrying the same sentence: fixtures/agent-context-conformance/ts-react-tanstack/expected/.metaobjects/AGENTS.md:76, java-react/.../AGENTS.md:66, csharp/.../AGENTS.md:64, python/.../AGENTS.md:65, java-kotlin-react-tanstack/.../AGENTS.md:76. Secondary wording nit in the same template+fixtures: the Schema heading (line 14) says 'Java, C# and Python projects need Node too', omitting Kotlin, the fifth port reading the same file.docs/features/language-differences.md:48- The 'Hand edits to a generated file' row gave the overwrite escape only to Java/Kotlin, but C# (WithHandEdits(HandEdits.Overwrite), server/csharp/MetaObjects.Codegen/CodegenRunner.cs:105) and Python (handEdits: overwrite, server/python/src/metaobjects/codegen/config.py:71) ship the same escape (docs/features/own-your-codegen.md:698-701). Applied inline: the C# cell now reads 'Refused by name, or overwritten withWithHandEdits(HandEdits.Overwrite)' and the Python cell 'Refused by name, or overwritten withhandEdits: overwrite'.🔧 Fix applied.
📝 1 wording or comment-placement note left for the author (no fix round spent):
docs/ports/java.md:25- Inline fix: two port-page callouts began a sentence in lowercase after the bold lead-in (...Nodemetatool.** the Maven plugin generates...). Capitalised 'The' in both. Wording only, no behaviour change.cd server/typescript && bun testran past 24 minutes and was stopped at its 25-minute timeout with no exit status. Its partial log shows no failing tests, but completion is not established. The sdk (448) and cli (2026) suites pass, and the baseline ts-fast and ts-unit lanes passed. The outer executor should rerun the full server suite, or split it by directory, and record its exit status.server/typescript/packages/cli/src/commands/init.ts:454- In a repository that has only CLAUDE.md, init and refresh append the @.metaobjects/AGENTS.md import to CLAUDE.md alone and do not create AGENTS.md. Assistants that read only AGENTS.md (the goal of the assistant-neutral change) will not load the context in such repositories. Fresh projects are fine because both files are created. Whether to create AGENTS.md when only CLAUDE.md exists is a product-policy choice for the maintainer.server/typescript/packages/cli/src/commands/init.ts-meta init --docs-only --refresh-docsprints 'Scaffolded the MetaObjects agent context (N files)' rather than 'Refreshed'. The docsOnly branch is checked before the refreshedDocsOnly branch, and that ordering predates this change, so the refresh message is misleading.scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchainsBaseline (given): scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchains (passed)bun run --filter '*' build from the worktree (all TypeScript packages built, exit 0)node server/typescript/packages/cli/dist/bin/meta.js init --server typescript in a fresh temp project (S1)meta init --server java --skills-dir .agents/skills, then meta init --docs-only --refresh-docs with no flag (S2/S3)Local edits to .metaobjects/AGENTS.md and a skill, then --docs-only --refresh-docs: .new files written, edits preserved (S4)Adversarial --skills-dir ../escaped, /absolute/path, a/../../escaped2, '.' with exit codes and a check that nothing was written outside the project (S5)Re-run init to check root import idempotence; pre-existing CLAUDE.md content preserved with the import appended once (S6)Moving --skills-dir from .agents/skills back to default on refresh: unedited orphans pruned, manifest skillsDir cleared (S7)bun test in server/typescript/packages/runtime-ts test/drizzle-fastify/filter-mount-list.test.ts and mount-read-only.test.ts: 80 pass (S8, real Fastify routes over in-memory libsql, filter.bare_field and filter[field][eq] forms)Config-only Java-rooted project: meta init --config-only, meta migrate --from-db --dialect sqlite --slug init --apply, meta migrate apply-pending --db file:other.sqlite, meta verify --db file:other.sqlite (S9, all exit 0)meta agent-docs --server csharp --server python --skills-dir .agents/skills (S10)python3 -m pytest server/python/tests/codegen/test_hand_edits.py: 7 pass; keep and overwrite parametrized cases drive the real metaobjects CLI main(['gen']) (S11)cd server/typescript/packages/sdk && bun test: 448 tests passcd server/typescript/packages/cli && bun test: 2026 tests passFull TypeScript server suite (cd server/typescript && bun test) started; no result after 24 minutes, killed at the 25-minute limit. Partial log shows zero (fail) lines but no completion. Not established.🔧 Fix applied.
1 info still open:
meta init --refresh-docs --skills-dir <new>moves the skills install, the old directory's FILES are all pruned (documented behavior, manifest tracks files) but the empty directory husks (e.g..agents/skills/metaobjects-audit/references/) remain on disk, which can read as 'the old copy is still there'. Cosmetic only; nothing is committed by git and no content survives.meta init --server typescriptin an empty disposable project is assistant-neutral: root AGENTS.md AND CLAUDE.md created each carrying the pointer line + @.metaobjects/AGENTS.md import, only .m…metaobjects --help(py3.11 venv) lists gen/verify/fmt/eject/init/deps with no migrate, andmetaobjects verify --db sqlite:///demo.dbrefuses…scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchainsscripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchains (configured baseline, ran before this step, passed)scripts/ci-local.sh --only ts-slow --strict-toolchains (this step: LOCAL CI PASSED, 9m11s — integration-tests TS + real-Postgres migrate-ts)node server/typescript/packages/cli/dist/bin/meta.js init [--docs-only] [--refresh-docs] [--skills-dir ...] driven in disposable projects under the evidence dir (S1–S5)npx -y @metaobjectsdev/cli@1.2.0 init then refresh with this branch's CLI — 1.2.0→1.3.0 upgrade cases A and B (S6–S7)bun test runtime-ts: test/drizzle-fastify/filter-mount-list.test.ts + mount-read-only.test.ts (82 pass) plus a throwaway 60-row no-limit test (2 pass, deleted after capture)dotnet test MetaObjects.Codegen.Tests --filter FullyQualifiedName~OrphanSweepTests (14/14); dotnet test MetaObjects.Cli.Tests --filter AgentContextStaleness (14/14); dotnet run --project MetaObjects.Cli -- --helpmvn -pl codegen-base -am test -Dtest='OrphanSweepTest,GeneratedFileWriterTest' (18+26, 0 fail); mvn -pl metadata -am test -Dtest=AgentContextStalenessTest (19/19)pytest tests/unit/test_agent_context_staleness.py tests/codegen/test_cli_staleness_nudge.py in a disposable py3.11 venv (26 passed); metaobjects --help; metaobjects verify --db sqlite:///demo.db (refusal captured)🔧 **Document** - 1 issue found → auto-fixed ✅
agent-context/skills/metaobjects-codegen/references/principles.md:15- One leftover Claude-only mention survives in the assistant-neutral agent context this change built: the sharedmetaobjects-codegenreference still says a project that deliberately owns its schema by hand records that rule "when the rootCLAUDE.mdsays so, follow it" — naming only CLAUDE.md where the always-on text everywhere else now saysAGENTS.mdorCLAUDE.md. The same sentence is byte-copied into all fivefixtures/agent-context-conformance/*/expected/.claude/skills/metaobjects-codegen/references/principles.mdcopies, so fixing it means editing the skill source (product output scaffolded into consumer projects) and regenerating five fixture files — both outside this documentation phase's lane (no product content or test changes). Not factually false, just incomplete relative to the neutrality intent the change's own CHANGELOG entry claims ("The text no longer tells the reader to use a rootCLAUDE.mdonly").🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.