Skip to content

Tooling: ComponentSerializerCoverageTest forward check only scans Components.h -> forgotten non-trivial subsystem-header component escapes the data-loss guard #545

Closed

Description

@drsnuggles8

Summary

ComponentSerializerCoverageTest.EveryDeclaredComponentIsHandledBySceneSerializer — the guard that is supposed to catch "you added a component and forgot to serialize it" (the #325-class silent-data-loss species) — builds its declared universe from the raw text of Components.h only. Components declared in subsystem headers (not Components.h) are outside its universe, so a forgotten non-trivial subsystem-header component escapes the check entirely.

Evidence

  • ComponentSerializerCoverageTest.cpp:83: headerSrc = ReadFile(componentsHeader) (a raw text read — #includes are not expanded); line :96 iterates the struct \w+Component regex over headerSrc only.
  • Many serialized components live outside Components.h: e.g. struct InventoryComponent in Gameplay/Inventory/InventoryComponents.h (hand-written serialize SceneSerializer.cpp:5282, deserialize :3090); likewise AbilityComponent, IKTargetComponent, QuestJournalComponent, NavMeshBoundsComponent, StreamingVolumeComponent, the AI components, etc.
  • The asymmetry: the sibling ComponentTupleCoverageTest (ComponentHeaderRoots(), ~16 headers) and the inverse half of this same test (componentHeaderRoots, ~line 187) both scan the full subsystem-header list. Only the forward check regressed to Components.h-only. (CLAUDE.md's "greps a fixed header list" describes the inverse check — the forward missing-serialization guard does not cover subsystem headers.)

Reproduction

Add a non-trivial component (e.g. struct FooComponent with a Ref<T> field) to any subsystem header (say AIComponents.h) and forget its hand-written SceneSerializer.cpp block. It is classified non-trivial (so not auto-generated), never hand-written, and not in declared (not in Components.h) → the forward test passes → silent scene-YAML data loss ships, undetected by the very guard meant to prevent it.

Fix direction

Repoint the forward check's declared set at the full header-root list the inverse check + ComponentTupleCoverageTest already use (ComponentHeaderRoots() / componentHeaderRoots), so the forward and inverse checks share one component universe. Trivial change; it closes a real hole in a data-loss safety net.

Score

capability: 1
craft: 1
stability: 5
decay: 3
effort: 1
confidence: 1.0
learning: 1
fun: 2
kano: table-stakes
blocked_by: []
blocks: []

Rated per issue-scoring · score = confidence × (capability + craft + stability + decay) / effort, derived by the picker.

Activity

  1. added
    robustnessProduction hardening / shipping robustness
    toolingTier 1: MCP, dev tooling, codegen, CI, test infra. Freeze-exempt; start-work Tier-1 slot
    on Jul 4, 2026
  2. coderabbitai commented on Jul 4, 2026

    @coderabbitai
    Contributor
    🔗 Related PRs

    #330 - Fix/savegame component coverage [merged]
    #405 - Codegen: generate the SaveGame component capture/restore lists (#380) [merged]
    #467 - feat(codegen): SceneSerializer blocks for AssetHandle/UUID-field components (#451) [merged]
    #477 - feat(codegen): SceneSerializer enum-field support (#451 slice) [merged]
    #482 - feat(codegen): SceneSerializer glm-math / small-int / std::vector support (#451 slice) [merged]


    🧪 Issue enrichment is currently in open beta.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrobustnessProduction hardening / shipping robustnesstoolingTier 1: MCP, dev tooling, codegen, CI, test infra. Freeze-exempt; start-work Tier-1 slot

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions