AyCode.Core/AyCode.Core/docs/TOON/TOON_ISSUES.md

8.9 KiB

Toon — Known Issues

For planned/actionable work see TOON_TODO.md.

ACCORE-TOON-I-B7L4: Compact preset XML doc contradicts code behaviour

Severity: Trivial (doc-only, no runtime effect) · Status: Open (direction not decided) · Area: Serializers/Toons/AcToonSerializerOptions.cs

Description

The XML doc on AcToonSerializerOptions.Compact claims "Minimal output, no meta, no indentation", but the property initializer sets UseIndentation = true. Real output is DataOnly + no type names + no reference handling with indentation whitespace. Consumers reading IntelliSense expect a tighter output than they receive.

/// <summary>
/// Compact mode: Minimal output, no meta, no indentation.   ← doc says no indent
/// ...
/// </summary>
public static AcToonSerializerOptions Compact => new()
{
    Mode = ToonSerializationMode.DataOnly,
    UseMeta = false,
    UseIndentation = true,                                      code sets true
    ...
};

Root cause

Likely the XML comment predates a later preset revision that flipped UseIndentation to true. The comment was not updated to match.

Fix options (undecided)

  • (a) Fix the doc — update the XML comment to match current behaviour. "Compact" then means "DataOnly, no type names, no refs" — not literal whitespace-free.
  • (b) Fix the code — flip UseIndentation to false in the preset to honour original intent. Output-breaking change for anyone relying on current Compact formatting.

Known workaround

Build a custom options instance when truly token-minimal output is needed:

var trulyCompact = new AcToonSerializerOptions {
    Mode = ToonSerializationMode.DataOnly,
    UseMeta = false,
    UseIndentation = false,
    OmitDefaultValues = true,
    WriteTypeNames = false,
    ReferenceHandling = ReferenceHandlingMode.None
};

TOON_OPTIONS.md already notes this divergence next to the Compact preset; decision here governs whether it persists or gets resolved.

None yet — fix direction not decided.

ACCORE-TOON-I-X3H2: Age inference substring false positive

Severity: Minor (constraint-only, no runtime effect) · Status: Open · Area: Serializers/Toons/AcToonSerializer.Descriptions.csGetPropertyConstraints / GetInferredConstraints

Description

Integer properties whose name contains the substring age (case-insensitive, not word-bounded) erroneously receive the range: 0-150 constraint from the Age inference rule. False positives observed: LanguageId, and by pattern Package*, Image*, Page*, Message*, Storage*, Stage*.

Observed in a 2026-04-24 Toon dump:

LanguageId: int?
  constraints: "range: 0-150"

Root cause

if (propertyName.Contains("Age", StringComparison.OrdinalIgnoreCase))
    constraints.Add("range: 0-150");

"LanguageId".Contains("Age", OrdinalIgnoreCase) returns true — the substring age sits at position 5-7 inside Language. The rule's intent was to match an Age-named property, but Contains has no word-boundary awareness.

Fix options

  • (a) Exact match: propertyName.Equals("Age", OrdinalIgnoreCase) — loses legitimate matches like CustomerAge, MinAge.
  • (b) Suffix: propertyName.EndsWith("Age", OrdinalIgnoreCase) — still matches Language (ends in age).
  • (c) Word-boundary regex — accurate but adds a regex pass per property.
  • (d) EndsWith("Age") + preceded-by-uppercase guard — CustomerAge ok (rA capital transition), Language rejected (ua lowercase transition).

Similar risk applies to other substring-based rules in Descriptions.cs (Email, Phone, Address, Url, Date, Version, CreatedAt, UpdatedAt, DeletedAt) — audit them under the same word-boundary lens.

Known workaround

Explicit [ToonDescription(Constraints = "...")] on the affected property (replace mode — no placeholder).

None yet.

ACCORE-TOON-I-P6V5: Property override duplicated on inheritance in @types

Severity: Minor (schema correctness; LLM may misinterpret) · Status: Open · Area: Property enumeration — likely AcToonSerializer.ToonSerializeTypeMetadata.cs or the shared base in Serializers/ root.

Description

When a derived class uses override on a property inherited from its base, both the derived and the base version appear in the @types schema — two entries for the same logical member, each with its own business-logic string.

Observed in a 2026-04-24 Toon dump on OrderItemPallet:

OrderItemPallet:
    ...
    MeasuringStatus: MeasuringStatus
      business-logic: "get => IsAudited ? MeasuringStatus.Audited : base.MeasuringStatus"
      constraints: "readonly, not-mapped"
    ...
    MeasuringStatus: MeasuringStatus
      business-logic: "get => IsMeasured ? MeasuringStatus.Finnished : Id > 0 ? ..."
      constraints: "readonly, not-mapped"

Only affected when a class uses override on a property. Sibling non-overriding classes (ShippingItemPallet, StockTakingItemPallet) emit the property once as expected.

Root cause (likely)

Type.GetProperties(BindingFlags.Public | BindingFlags.Instance) returns overridden properties twice — once per declaring type in the inheritance chain. The Toon property enumeration does not dedupe on Name, so both versions reach the writer.

Fix options

  • (a) Filter in the metadata build step: group by Name, keep the most-derived override (lowest inheritance distance from the target type).
  • (b) Walk the inheritance chain with BindingFlags.DeclaredOnly per level, collecting names into a set; skip if already seen.

Known workaround

None — the schema is wrong as-is. Downstream consumers must tolerate the duplicate entry.

None yet.

ACCORE-TOON-I-K4Z9: Property order in @types is not pure alphabetical

Severity: Minor (readability / predictability) · Status: Open · Area: Property ordering — likely AcToonSerializer.ToonSerializeTypeMetadata.cs, inherited from the shared base in Serializers/ root.

Description

Per-class property emission in @types is hierarchy-aware derived→base, with alphabetical order within each inheritance level. The inherited Id property therefore appears at the very end of every class definition, instead of its alphabetical slot between H… and J….

Observed in a 2026-04-24 Toon dump on Customer (simplified):

Customer:
    Active, AdminComment, ..., ZipPostalCode,    ← own properties, alphabetical
    Id                                            ← inherited, placed LAST

And on OrderItemPallet (which has multi-level inheritance):

OrderItemPallet:
    AverageWeight, IsAudited, MeasuringStatus, ..., TrayQuantity,  ← derived-class props
    Created, CreatorId, ForeignKey, ..., TrayQuantity,             ← base class props
    Id                                                              ← base-base entity

Expected behavior

Pure alphabetical order across all properties of the type, regardless of inheritance level. For Toon's LLM-readability goal, a predictable flat order matters more than hierarchy preservation.

Docs inconsistency

Serializers/README.md "Property ordering" section states: "Hierarchy-aware (base→derived) then alphabetical. Ensures stable property indices across type versions." Two mismatches with actual behavior:

  1. Direction reversed — real output is derived→base, not base→derived as the doc claims.
  2. Rationale irrelevant to Toon — "stable property indices across type versions" is a wire-format concern for AcBinary. Toon is a descriptive schema format where property order is cosmetic, not semantic.

Fix options

  • (a) Override the property ordering specifically in ToonSerializeTypeMetadata to plain OrderBy(p => p.Name) — Toon diverges from the Binary/JSON shared ordering. Recommended: AcBinary needs the hierarchy-aware order for wire stability; Toon does not, and can opt out.
  • (b) Fix the direction in the shared base (base→derived as the docs claim) — partial fix, still not pure alphabetical.
  • (c) Accept current behavior and update Serializers/README.md to match observed reality — reject the issue. Not recommended: the user expectation is pure alphabetical, and the docs-vs-code gap is real either way.

Known workaround

None — consumers must tolerate the current order.

None yet. Fix also requires reconciling Serializers/README.md with the chosen direction.

Issue entry template

## ISSUE-NN: Short title

**Severity:** Trivial / Low / Minor / Major · **Status:** Open / Documented / Mitigated · **Area:** <subsystem>

### Description
What breaks, and under what conditions.

### Root cause
Why it happens (code location + design mismatch).

### Known workaround
Steps a consumer can take until fixed.

### Related TODO
`TOON_TODO.md#todo-NN` (if applicable).