Repository navigation
fix(loader): register view.* subtypes and inline attr.properties in Python, C# and Java - #401
Merged
Merged
Conversation
…thon, C# and Java An undeclared inline attribute whose value is a JSON object is the registered attr.properties bag, the same node the explicit attr.properties child form produces. TypeScript already loaded it that way; the other loaders each diverged differently: - Python loaded it as attr.base and failed strict mode with ERR_UNKNOWN_ATTR. - C# rejected the value with ERR_BAD_ATTR_VALUE. - Java (and Kotlin, which shares its loader) loaded it but stored the bag as a JSON-text string, so the canonical output differed. Each parser now materializes the bag at the inline-attribute site. Gated by the new shared attr-properties-inline conformance fixture. Nothing that loaded before stops loading; no new error codes or vocabulary.
…on, C# and Java A document carrying view.text, view.dropdown or any other web-presentation control loaded in TypeScript and failed with ERR_UNKNOWN_SUBTYPE in Python, C# and Java (and Kotlin, which shares the Java loader). Those ports had left the controls unregistered on purpose, as vocabulary with no backend consumer, which made metadata shared between a TypeScript web client and a backend port unloadable in the backend. Every port now registers the same view subtype list as TypeScript. The controls stay presentation-only: no backend generator reads them, and each manifest emitter still classifies them PRESENTATION_ONLY, so expected-registry.json and metamodelVersion do not move. Gated by the new shared view-text-basic conformance fixture. The registry conformance README, CONFORMANCE.md, the audit skill and the code comments that described the old ruling are corrected.
…across features, ADR
…ounding exemption
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.
Intent
Fix two reported Python-port load defects in metaobjects, found by a downstream consumer's research against 1.0.11 and believed to still exist on main:
view.*subtypes: a document usingview.textfails withERR_UNKNOWN_SUBTYPEin Python but loads in TypeScript."@mongo": {"collection": "orders"}, the recipe's own example) loads asattr.propertiesand passes strict mode in TypeScript, but loads asattr.baseand fails strict mode withERR_UNKNOWN_ATTRin Python. The explicit{"attr.properties": {"name": ..., "value": {...}}}child form passes in Python.The worker verifies both on main, checks the C#, Java and Kotlin ports for the same gaps, and adds conformance fixtures. Fix now, gated; the gate spend is approved.
Decision on item 1, after it turned out to be a documented deliberate ruling rather than an accidental gap: option B. Register the 12 generic view.* controls for loading in Python, C# and Java (Kotlin via the Java loader); keep them PRESENTATION_ONLY and excluded from expected-registry.json so the manifest and metamodelVersion do not move; add the shared view-text-basic conformance fixture; correct the README, CONFORMANCE.md, audit-skill and view_constants prose that state the old ruling.
What Changed
view.*presentation controls now load in Python, C# and Java (Kotlin via the Java loader). A document carryingview.textorview.dropdownloaded in TypeScript but failed withERR_UNKNOWN_SUBTYPEin the other ports. They register for LOADING only and stay PRESENTATION_ONLY and excluded fromexpected-registry.json, so the manifest andmetamodelVersiondo not move. Gated by the newview-text-basicconformance fixture; Java adds aPresentationViewregistration besideCurrencyView, and the manifest filters in all three ports keep them out of the cross-port contract.attr.propertiesbag in every port, matching TypeScript'sinferUndeclaredAttrSubType. Python previously loaded"@store": {...}asattr.base(strict load fails withERR_UNKNOWN_ATTR), C# rejected the object value withERR_BAD_ATTR_VALUE, and Java/Kotlin stored the bag as a JSON-text string. Gated by the newattr-properties-inlineconformance fixture. Nothing that loaded before stops loading.fixtures/registry-conformance/README.md(B-2),docs/CONFORMANCE.md,docs/features/image-upload.md, the base-subtypes migration note, ADR-0054, the audit skill and capability checklists, the Java manifest-conformance test prose and the TS "11 controls" test updated to 13, plus a regenerated showcase site payload.Risk Assessment
✅ Low: Well-bounded two-defect port-parity fix: each parser change mirrors the existing TS reference path, manifest immobility is guaranteed by classification-based (not name-list) exclusion, the corpus count gates (scripts/site/counts.test.ts) are satisfied by the updated numbers, and the only findings are a stale comment and a pre-existing latent Java value-stringification boundary — neither blocks merge.
Testing
Baseline configured command (scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchains) had already run green before this phase. I derived the intent (Python/C#/Java/Kotlin loader parity for view.* subtypes and inline object-valued attrs as attr.properties, with the registry manifest frozen) and drove both defects live: the Python loader now strict-loads view.text/view.dropdown and the inline \"@store\" object attr as attr.properties (8/8 checks, canonical output byte-matching both new shared fixtures, which also pass the Python conformance corpus runner), TypeScript shows identical behavior (6/6 checks), and the adversarial cases hold — strict mode still rejects an unknown scalar attr (ERR_UNKNOWN_ATTR) and an unregistered view.bogus (ERR_UNKNOWN_SUBTYPE) in both ports. Registry manifest was checked only by static diff (expected-registry.json unchanged, METAMODEL_VERSION untouched) — not a live drive, so that scenario is now reported untested rather than passed. The broad regression run (ts-fast + ts-unit + java + csharp + python lanes) went green through ts build/typecheck, conformance: typescript and ts-unit startup, then was stopped at the mutation gate when this phase had to report, so the mutation, java, kotlin, csharp and python-full lanes did not run; the python+TS live drives stand as the direct evidence, and C#/Java/Kotlin parity is unverified live in this run. Evidence transcripts are in the evidence directory; no worktree files were left behind (scratch drivers created and removed; temp docs under /tmp cleaned).
Evidence: Python loader live drive — both defects fixed, strict mode preserved (8/8 PASS)
Evidence: TypeScript parity live drive (6/6 PASS)
Evidence: Adversarial — unregistered view.bogus still rejected in python and TS
python: codes=['ERR_UNKNOWN_SUBTYPE'] [PASS] ts: codes=ERR_UNKNOWN_SUBTYPE [PASS]Evidence: Partial regression log — TS lanes green, stopped at mutation-gate start
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
🔧 **Rebase** - 2 issues found → auto-fixed ✅
CHANGELOG.md- merge conflict rebasing onto origin/maindocs/CONFORMANCE.md- merge conflict rebasing onto origin/main🔧 Fix applied.
✅ Re-checked - no issues remain.
server/csharp/MetaObjects/RegistryManifest.cs:42- Stale comment still states the retired ruling: "the 11 genericview.*controls are a TS-web-presentation facet (cut cross-port; C#/Python deregister them, TS keeps them registered)". Both claims are now false (13 controls, registered in every port). The intent explicitly asked to correct prose that states the old ruling, and the twin Java comment (RegistryManifest.java:288-291) was updated in this change — the C# copy was missed.server/java/metadata/src/main/java/com/metaobjects/loader/parser/json/CanonicalJsonParser.java:1445- Loading parity is achieved, but the CHANGELOG claim "All four loaders now agree" holds only for string-valued bags: Java's PropertiesAttribute.setValueAsString stringifies every bag value (numeric 5 becomes "5", a nested object becomes a compact JSON string), while TS/Python/C# preserve the JSON type, someta fmtbyte output would diverge across ports for a numeric- or nested-valued inline bag. Pre-existing behavior of the explicitattr.propertiesform (attr-properties-basic also uses only string values), not a regression — the old Java inline path stored the whole bag as one JSON-text string, which was worse. The new attr-properties-inline fixture only covers a string-valued bag, so the corpus cannot catch this. Informational: a follow-up fixture plus typed-value preservation in Java PropertiesAttribute would close it; no action required within this change's stated intent.scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchainsuv run --extra integration pytest tests/conformance/test_conformance.py::test_conformance[view-text-basic] ::test_conformance[attr-properties-inline] (python corpus runner, both new fixtures) — 2 passedpython public loader drive: MetaDataLoader.from_directory(strict=True) over the two fixture inputs plus a hostile doc — 8/8 assertions (strict load, view.text/view.dropdown children present, canonical == expected.json, @store as attr.properties bag {collection: orders}, unknown scalar attr → ERR_UNKNOWN_ATTR) — transcript evidence/py-loader-drive.txtTypeScript parity drive: MetaDataLoader.fromDirectory({strict:true}) from server/typescript/packages/metadata over the same inputs — 6/6 assertions (view.text loads, canonical == expected.json, inline @store as attr.properties, strict still rejects unknown scalar attr) — transcript evidence/ts-loader-drive.txtadversarial: unregistered view.bogus child under field.string strict-loaded in python and TS — both return ERR_UNKNOWN_SUBTYPE, proving the registration is the enumerated control list, not a wildcard — evidence/adversarial-view-bogus.txtgit diff e2456aa23..4301ed700 -- fixtures/registry-conformance/expected-registry.json — 0 lines; METAMODEL_VERSION still "1.1" in registry-manifest.ts; no constants/ changes — manifest and metamodelVersion frozen (static file-state evidence only, not a live drive)scripts/ci-local.sh --only ts-fast --only ts-unit --only java --only csharp --only python --strict-toolchains — launched; ts build + typecheck ✓, conformance: typescript ✓ (0 fail across its suites), ts unit suites started; run stopped at completeness-gate (mutation) start when the phase had to report; java/kotlin/csharp/python lanes not reached — partial log evidence/regression-partial.logagent-context/skills/metaobjects-audit/references/capability-checklist.md:178- The audit checklist's CALIBRATION bullet still enumerates the generic view.* widgets WITHOUT view.image (12 items), while this change corrected the owner (fixtures/registry-conformance/README.md B-2) to 13 including image, and the backend ports now register all 13. The same 12-item list lives in server/typescript/packages/sdk/test/agent-context-capability-grounding.test.ts EXEMPT_SUBTYPES, and that test's title also says 'manifest cuts the 11 generic view.* controls'. I could not fix this here: naming view.image in the checklist fails the grounding test (view.image is absent from both expected-registry.json, because it is manifest-excluded, and EXEMPT_SUBTYPES), so the fix needs the test's exemption set widened in the same commit, plus the identical edit in the 6 byte-mirrored copies under fixtures/agent-context-conformance/*/expected/.claude/skills/metaobjects-audit/ — all outside this docs-only phase.docs/superpowers/specs/2026-07-18-form-controls-view-dispatch-design.md:94- Dated design/plan records still state the old B-2 ruling ('view.textarea is deregistered in C#/Python/Java'): docs/superpowers/specs/2026-07-18-form-controls-view-dispatch-design.md, docs/superpowers/plans/2026-07-18-form-controls-view-dispatch.md, docs/superpowers/specs/2026-07-19-image-support-design.md, docs/superpowers/plans/2026-06-02-sp-g-java-reconciliation-plan.md. Left deliberately: they are dated decision archives, and every live surface (registry README B-2, audit skill, CHANGELOG, feature docs, ADR-0054 amendment) now states the current ruling. Rewriting archives would be a broader docs-consolidation pass, not part of this change.🔧 Fix applied.
1 info still open:
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.