fix(codegen): resolve @objectRef to bare class name + use resolution_key for header FQN#28
Merged
Merged
Conversation
…key for header FQN Two multi-file / nested-ref codegen correctness fixes: - @objectref is FQN-expanded at load time; the value/entity generator emitted list[pkg::Thing] and a 'from .pkg::Thing import' line (invalid Python). The type annotation and relative import now use the bare class name. - The four header-FQN helpers did a naive nearest-ancestor package walk, so after a multi-file merge every object folded onto the alphabetically-first file's package. Route them all through MetaData.resolution_key() (own -> file-default -> ancestor), which already handles the merged-tree case. Regression tests added for both. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
dmealing
added a commit
that referenced
this pull request
Jun 15, 2026
#30) Cross-port audit of the two bug patterns fixed for Python in PR #28: BUG A — `@objectRef` emitted as a RAW FQN in a generated type reference / import, where it must be the BARE short name (last `::` segment). BUG B — a naive nearest-ancestor package walk for an entity's header FQN, where it must use the canonical resolution key. Audit result across the four remaining ports: - Java (codegen-spring): both clean — SpringNaming.splitFqn() already strips refs and derives package from the load-time-qualified entity name. - Kotlin (codegen-kotlin): both clean — same JVM splitFqn() strategy. - C#: BUG A present in PayloadCodegen; BUG B clean (PackageBindingResolver.EffectivePackage already uses ResolutionKey). - TS: BUG A present in three value-object/entity emitters; BUG B clean (docs-paths.effectivePackage already uses resolutionKey()). BUG B is therefore not present in any port — every engine derives the entity package from its canonical resolution key / load-time-qualified name. Only BUG A needed fixing, in C# and TS: - C# PayloadCodegen.FieldType / BuildTree: a fully-qualified nested @objectref emitted `IReadOnlyList<acme::ai::Brief>` (invalid C#) AND the nested-record lookup (FindObject matches bare names) missed, dropping the nested record entirely. Now StripPkg() before use, matching every other C# generator. - TS valueObjectFieldType / zod insert-schema / sqlite isArray $type: a fully-qualified ref emitted an invalid identifier + a colon-laden sibling module path. Now stripPackage() before use, matching the existing string form fieldTsTypeString(). Regression tests added at each fixed site (C# PayloadCodegenTests, TS column-mapper / zod-validators / value-object-file). The cross-package behavior-corpus gate (a multi-file/multi-package @objectref roundtrip in persistence-conformance) is deferred to the multi-package conformance work per the standing FR-007 policy that codegen drift is gated through behavior corpora, not a codegen-output corpus. Co-authored-by: Claude Opus 4.8 (1M context) <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
Two Python-codegen correctness fixes surfaced when a payload's
object.valuereferenced another value-object via
@objectRefacross multiple metadata files.1.
@objectRefemitted as a raw FQN@objectRefis FQN-expanded at load time (e.g.app::pkg::Thing). The value/entity generator emitted the expanded form directly, producing invalid Python:
The type annotation and the relative import now use the bare class name
(
type_map.py+entity_model.py), since all generated VOs live flat in onepackage.
2. Header FQN folded onto the wrong package after a multi-file merge
The four codegen header-FQN helpers (
entity_model,router,filter_allowlist,payload_vo) did a naive nearest-ancestor package walk.After a multi-file merge every node hangs under one package-less merged root,
so each object folded onto the alphabetically-first file's package — e.g. an
object declared in
b.yaml(packageb) would be labelled with packagea.They now delegate to the canonical
MetaData.resolution_key()(own package →file-default package captured at parse → nearest ancestor), which already
handles the merged-tree case. For single-file metadata this is identical to the
old walk, so existing output is unchanged; only the multi-file case is corrected.
Tests
Added regression tests in
tests/codegen/test_entity_model.pyfor both: anFQN-expanded
@objectRefshortening to the class name, and the header FQNfolding the file-default package after a merge. Full codegen suite green.
🤖 Generated with Claude Code