Skip to content

Commit c101751

Browse files
dmealingclaude
andcommitted
feat(csharp): FR-013/014/015 loader validation passes (per-port fan-out)
Ports the three deferred validation passes from the TS reference into the C# loader (ValidationPasses), clearing all 10 deferred error fixtures from the C# conformance ledger. - FR-013 ValidateFieldReadOnly — ERR_READONLY_ASSIGNED_PRIMARY, ERR_READONLY_DOWNGRADE, WARN_READONLY_VALUE_OBJECT. - FR-014 ValidateDiscriminator — ERR_DISCRIMINATOR_FIELD_NOT_FOUND, _VALUE_DUPLICATE, _VALUE_MISSING, _VALUE_TYPE_MISMATCH (4-pass). - FR-015 ValidateSourceParameterRef — ERR_PARAMETER_REF_ON_NON_CALLABLE_KIND (pre-resolution), _UNRESOLVED, _NOT_VALUE_OBJECT, _PASSTHROUGH_TYPE_MISMATCH. Wired into MetaDataLoader.Load after the FR-016 physical-name pass; each mirrors its TS counterpart's logic + error-code/envelope contract (collect-not-throw, C# idiom). WARN_READONLY_VALUE_OBJECT added to WarningCodes. Unlike Java, the C# model preserves an override field's authored JsonSource, so error-field-readonly-downgrade emits the byte-identical envelope and passes. C# conformance: 550/550 passed, ledger cleared. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent b588175 commit c101751

4 files changed

Lines changed: 378 additions & 13 deletions

File tree

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
11
{
22
"language": "csharp",
33
"_comment": "FR5a envelope-shape gates: TS is the reference port for source.format / source.files / source.jsonPath. C# is now reconciled with TS on the JSON-side FR5a envelopes (parser malformed-JSON catch builds a $-rooted JsonSource with the source-file name; inline-attr loop reports ERR_RESERVED_ATTR / ERR_UNKNOWN_ATTR / ERR_BAD_ATTR_VALUE at the parent's path — not key-deeper). Keep this file as the documented ledger surface.",
4-
"_notes": "FR5c (finalized 2026-05-27, all four ports): merge-phase contributors + ERR_MERGE_CONFLICT envelope + WARN_DUPLICATE_DECLARATION. FR5d (finalized 2026-05-27, all four ports): reference-resolution errors emit format=resolved with referrer + target. FR-013 (@readOnly), FR-014 (TPH discriminator), and FR-015 (@parameterRef) attrs are now registered in the C# registry vocabulary (SP-G registry-conformance), so positive round-trip fixtures pass; their VALIDATION passes have not yet shipped in the C# port, so the error-* fixtures remain deferred until each per-port fan-out lands.",
5-
"fixtures": [
6-
"error-field-readonly-assigned-primary",
7-
"error-field-readonly-downgrade",
8-
"error-parameter-ref-unresolved",
9-
"error-parameter-ref-not-value-object",
10-
"error-parameter-ref-on-table-kind",
11-
"error-parameter-ref-passthrough-type-mismatch",
12-
"error-tph-discriminator-field-not-found",
13-
"error-tph-discriminator-value-duplicate",
14-
"error-tph-discriminator-value-missing",
15-
"error-tph-discriminator-value-type-mismatch"
16-
]
4+
"_notes": "FR5c (finalized 2026-05-27, all four ports): merge-phase contributors + ERR_MERGE_CONFLICT envelope + WARN_DUPLICATE_DECLARATION. FR5d (finalized 2026-05-27, all four ports): reference-resolution errors emit format=resolved with referrer + target. FR-013 (@readOnly), FR-014 (TPH discriminator), and FR-015 (@parameterRef) VALIDATION passes shipped in the C# port (ValidationPasses.ValidateFieldReadOnly / ValidateDiscriminator / ValidateSourceParameterRef); all error-* fixtures now produce the expected envelopes. No interim known-gaps.",
5+
"fixtures": []
176
}

server/csharp/MetaObjects/Errors.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ public static class WarningCodes
9696
/// serializer rewrites the attr key to the kind-matching alias.
9797
/// </summary>
9898
public const string WARN_LEGACY_PHYSICAL_NAME_ALIAS = "WARN_LEGACY_PHYSICAL_NAME_ALIAS";
99+
100+
/// <summary>
101+
/// FR-013: <c>@readOnly: true</c> on a field child of an <c>object.value</c>.
102+
/// Value-objects have no persistence semantics, so the read-only contract is
103+
/// advisory (codegen may use it for record/struct treatment).
104+
/// </summary>
105+
public const string WARN_READONLY_VALUE_OBJECT = "WARN_READONLY_VALUE_OBJECT";
99106
}
100107

101108
/// <summary>

server/csharp/MetaObjects/Loader/MetaDataLoader.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,24 @@ public LoadResult Load(IReadOnlyList<IMetaDataSource> sources)
377377
}
378378
}
379379

380+
// FR-013: field-level @readOnly cross-attribute rules.
381+
var roResult = ValidationPasses.ValidateFieldReadOnly(root);
382+
errors.AddRange(roResult.Errors);
383+
if (roResult.Warnings.Count > 0)
384+
{
385+
envelopeWarnings.AddRange(roResult.Warnings);
386+
foreach (var w in roResult.Warnings)
387+
{
388+
warnings.Add(w.Message);
389+
}
390+
}
391+
392+
// FR-014: TPH discriminator cross-attribute rules.
393+
errors.AddRange(ValidationPasses.ValidateDiscriminator(root));
394+
395+
// FR-015: source.rdb @parameterRef typed-input rules.
396+
errors.AddRange(ValidationPasses.ValidateSourceParameterRef(root));
397+
380398
// Pass 14 (FR-017): M:N relationship slim-vocabulary validation —
381399
// symmetric-self-join-only / symmetric⊕sourceRefField (ERR_BAD_ATTR_VALUE);
382400
// junction-two-references / sourceRefField-match / M:N-attr-on-1:N

0 commit comments

Comments
 (0)