feat(verify)!: strict-by-default with --lax escape (ADR-0023 cross-port consistency) (#96)#101
Merged
Merged
Conversation
…rt consistency) (#96) `meta verify` (TS) and `metaobjects verify` (Python) now load metadata strict by default: an undeclared/typo'd own @attr is ERR_UNKNOWN_ATTR and verify exits non-zero. This closes the ADR-0023 gap where such an attr silently passed verify in TS/Python but was rejected by Java's Maven metaobjects:verify goal (which already forces strict via LoaderOptions.create(false,false,true)). A new --lax flag restores the legacy open-attr load. Scope is verify only — gen / docs / agent-docs keep loading lax. The failure message points the author at the three exits: register the attr on a provider, use the attr.properties bag, or --lax. Also makes loadMemory's Meta Forge descriptive layer strict-clean: the forge provider now admits its types (decision/principle/…) under metadata.root and registers the @forge* provenance attrs as common attrs, so a real memory record verifies clean instead of ERR_CHILD_NOT_ALLOWED / ERR_UNKNOWN_ATTR. Dropped the retired @dbTable no-op attrs from the trainer-website test fixture (source.rdb @table already carries the physical name). Shared cross-port fixture (fixtures/verify-strict-conformance/) asserted by both the TS and Python CLI verify-strict tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LuZWKnWzYGVnESijL7uuky
This was referenced Jun 29, 2026
dmealing
added a commit
that referenced
this pull request
Jun 29, 2026
…) (#107) `dotnet meta verify` loaded metadata LAX, so an unregistered or typo'd own `@attr` silently passed verify in C# while Java's force-strict Maven goal and the strict TS/Python verify CLIs (#101) reject it — a port-dependent provenance verdict (ADR-0023). This completes the C# half of #96. - Thread `strict` through both verify load sites (`VerifyCommand.Run` and the `--codegen` gate) via a new `Options.Strict` (default true). The convenience `MetaDataLoader.FromDirectory` gains a `strict` param (default false / lax); `gen`/`docs`/`agent-docs` keep loading lax. - Add a `--lax` flag to `verify` arg parsing (sets strict=false) to restore the legacy open-attr load. - On a strict `ERR_UNKNOWN_ATTR` failure, print an actionable three-exit hint (register a provider / use an `attr.properties` bag / pass `--lax`). The loader error code/text is unchanged. TDD: VerifyStrictTests — a metadata dir with one made-up `@attr` FAILS verify by default (ERR_UNKNOWN_ATTR, exit 1) and PASSES with `--lax`. Cli/Conformance/ Codegen/Render suites all green; no repo-own fixture surfaced an unregistered attr. Part of #96. Claude-Session: https://claude.ai/code/session_01LuZWKnWzYGVnESijL7uuky Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
dmealing
added a commit
that referenced
this pull request
Jun 29, 2026
…als (#96) (#108) Under 7.5.x sealed strict provenance (ADR-0023) the Maven goals load force-strict, so an adopter mid-migration who still carries an unregistered @Attribute (real cases: @isJson, @dataflow*) is blocked from running metaobjects:generate / :verify — a hard upgrade-blocker. TS + Python verify already grew a --lax escape (#101); the Maven port had none. Add a shared `meta.lax` parameter on AbstractMetaDataMojo (inherited by the generate and verify goals — and the docs goal, which shares the base): @parameter(property = "meta.lax", defaultValue = "false") The flag flows to LoaderOptions.isStrict() on BOTH loader-creation paths — the LoaderOptions on the manual-loader path, and the `strict` loader argument (honored by MetaDataLoader.processArguments) on the configured-class path. Default (lax=false) is strict; -Dmeta.lax=true opts out. Also closes a latent gap: strict provenance is RECORD-not-throw at the loader (ADR-0023 records ERR_UNKNOWN_ATTR and continues), but the mojo never drained loader.getErrors(), so a strict violation passed silently. createLoader — the shared site for both goals — now fails the build on recorded loader errors and, for ERR_UNKNOWN_ATTR, appends an actionable hint (register a provider / use the attr.properties bag / -Dmeta.lax=true). The loader error code/text is unchanged; the hint is composed at the mojo level. Tests (TDD, RED→GREEN): MetaLaxStrictOptOutTest drives both mojos with a fixture carrying an unregistered @isJson — fails by default (naming the attr + the -Dmeta.lax=true escape), succeeds with lax=true — plus a unit assertion that lax=true => isStrict()==false and default => strict. The three pre-existing gen/docs tests share a fixture with a custom @simple::fruitbasket::isKey attr; they are provenance-agnostic, so their POMs now set <lax>true</lax> (the exact migration story this feature enables, and integration evidence the @parameter binds through real Maven config). maven-plugin module: 23 tests, 0 failures. Claude-Session: https://claude.ai/code/session_01LuZWKnWzYGVnESijL7uuky Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
dmealing
added a commit
that referenced
this pull request
Jun 29, 2026
…t (4 ports), formFile (#109) The squash-merges didn't carry per-PR CHANGELOG entries to [Unreleased]. Consolidate: - Correct + complete the verify strict-by-default entry to cover all four CLI ports and the #108 finding that Java was record-not-draining (silently passing), now a real fail-on-recorded-error gate + -Dmeta.lax (#101/#107/#108). - Add the jsonb open-bag → parsed-JSON-value contract change across all five ports (#98). - Add the formFile nested value-object sub-forms feature (#95). Claude-Session: https://claude.ai/code/session_01LuZWKnWzYGVnESijL7uuky Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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 & why
meta verify(TS) andmetaobjects verify(Python) now load metadata strict by default. An undeclared or typo'd own@attrisERR_UNKNOWN_ATTRand verify exits non-zero. This closes the ADR-0023 gap where such an attr silently passed verify in TS/Python but was rejected by Java's Mavenmetaobjects:verifygoal (which already forces strict viaLoaderOptions.create(false, false, true)).A new
--laxflag restores the previous open-attr load.Closes #96.
Breaking change
verifyis strict by default. A project whose metadata carries an attr no provider declares — a typo, or a vendor attr that was silently tolerated — now failsverify.Scope: only
verifydefaults strict.gen/docs/agent-docskeep loading lax (a possible follow-up: extend strict togen, deferred here).Migration (the failure message names all three):
attr.propertiesbag, ormeta verify --laxto keep the legacy open-attr load.Before / after
Implementation
LoadMemoryOptions.strictthreaded into the loader;verifypassesstrict: !flags.lax;parseVerifyArgsgains--lax; theERR_UNKNOWN_ATTRcatch prints the three-exit hint._load_root(..., strict=False)+_generate(..., strict=False)threaded;--codegen/--templatesverify paths passstrict = not args.lax;--laxadded to the verify subparser; same actionable hint.gen/docskeep the default-lax load.loadMemorybundles Meta Forge descriptive types (decision/principle/…) +@forge*provenance attrs so mixed content loads. Under strict these were rejected, so the forge provider now admits its types undermetadata.rootand registers@forge*as common attrs. Also dropped the retired@dbTableno-op attrs from thetrainer-websitetest fixture (source.rdb @tablealready holds the physical name).fixtures/verify-strict-conformance/(a registered node carrying one made-up@attr), asserted by both the TS and Python CLI verify-strict tests. The loader-level cross-portERR_UNKNOWN_ATTRgate already exists atfixtures/conformance/error-unknown-attr/(all five ports); Java's Maven goal already enforces strict.Test evidence
RED → GREEN per port:
verify-strict.test.ts— RED: strict default returned 0 /--laxunknown; GREEN after impl (3 pass).args-verify.test.tsupdated for thelaxfield + a--laxparse test.test_cli_verify_strict.py— RED:--codegen/--templatesreturned 0,--laxunrecognized; GREEN after impl (5 pass).Full suites:
bun test— 4826 pass, 2 fail (both pre-existing, confirmed on the clean base: a metamodel-docs byte fixture + a package-manager-detection test; neither touches verify/strict/forge). Whole-workspacetypecheckgreen.pytest tests/codegen— 257 pass, 2 fail (both pre-existing:test_cli_staleness_nudgeasserts an old"metaobjects agent-docs"string vs the current"npx meta agent-docs"message — unrelated to strict load).verify-subverbsfailures my change first surfaced (the forge-layer + stale-fixture findings above).🤖 Generated with Claude Code