Skip to content

push-to-neo: populateWindowSpec assumes 1 spec = 1 AD window, silently drops multi-window-merged entities #35

Description

@Gremiger

Summary

sf-push-neo (push-to-neo.js + neo-writer.js's populateWindowSpec) assumes a schema-forge spec maps to exactly one AD window. When a spec's contract.json legitimately merges entities sourced from multiple different AD windows/tabs (a supported, documented pattern — decisions.json entities are per-entity, not per-window), entities whose physical table has no tab under the spec's single resolved window are silently never created, and any manual DB patch for them is wiped on the next push.

Root cause (traced in source, not assumed)

  • resolveWindowId() resolves one window ID for the whole spec (contract.backendContract.window.id) and passes only that into populateSpec/populateWindowSpec.
  • populateWindowSpec (neo-writer.js:461) queries ad_tab WHERE ad_window_id = $1 using that single window ID — it has no visibility into any other AD window's tabs.
  • renameEntitiesToContractNames() (push-to-neo.js:571) then tries to relabel the auto-created entities to the contract's real entity names, matching by physical table name only (entityMapByTableName[tableForEntity]). If another entity in the merged spec happens to share a physical table with one of the single-window's own tabs, the rename "succeeds" by coincidence — but if the merged entity's physical table isn't among that one window's tabs at all, no entity is ever created, and every field insert for it fails with "no entity".
  • populateWindowSpec also runs deleteStaleEntities(), which deletes any entity that wasn't "visited" while walking that single window's tabs. This means any hand-inserted workaround entity for the missing tables gets silently deleted the next time anyone runs a normal sf-push-neo <spec> — it actively fights back against manual patches, not just a one-time gap.

Repro

A spec (calendar, in etendo_schema_forge, branch feature/ETP-4478) merges 4 entities from 3 different AD windows:

  • year — from window 117 (Fiscal Calendar) — the spec's registered window.
  • periodControl — from window E66E701CCBA14B8BA480CBDE37C50D7A (Open/Close Period Control) — table C_Period.
  • documents — from the same Open/Close Period Control window — table C_PeriodControl.
  • accounting — from window B5673F73F613496C8BEA22FB55E4E1E4 (End Year Close) — table FinancialMgmtAccountingFactEndYearHQL (HQL-backed).

Running sf-push-neo calendar:

  • year pushes correctly (its own window).
  • periodControl pushes "correctly" only because window 117 happens to also have its own period tab on the same physical table C_Period — the rename step relabels that unrelated entity. This is luck, not correct resolution.
  • documents (table C_PeriodControl, no tab under window 117) — entity never created; every field fails with "no entity".
  • accounting (table FinancialMgmtAccountingFactEndYearHQL, no tab under window 117) — same failure.

Suggested fix direction

populateSpec/populateWindowSpec should resolve each entity's source tab/window per entity, from contract.json (which already records a tabId/table per entity — this data exists, it's just not consulted here), instead of walking a single spec-wide ad_window_id. deleteStaleEntities needs the same per-entity-source awareness so it doesn't delete entities that are correctly sourced from a different window than the spec's "primary" one.

Related finding (same root assumption, different file)

extract-fields.js/regen-all.js's SKIP_EXTRACT flag has the identical "1 spec = 1 AD window" assumption baked in — it re-extracts from the spec's single registered windowId in cli/config/regen-windows.json regardless of SKIP_EXTRACT, clobbering a hand-merged multi-window schema-raw.json/rules-raw.json back down to one window's entities. Worth fixing both in the same pass since they're the same underlying gap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions