Story: Entity classification and drift baseline: ores.refdata pilot

Table of Contents

This page documents a story in Sprint 24. It captures the goal, current status, acceptance criteria, and the tasks that compose it.

Goal

We do not know how far ORE Studio's entities are from "regular": an up-to-date codegen model, fully current generated code, and any manual code confined to paste blocks. Several attempts to answer this already exist, independently, and none is trustworthy on its own:

This story reconciles all of the above into a single, unified, automated way of measuring drift: one tool that walks every codegen entity model and every generated/hand-crafted artefact across every component, classifies each entity along an agreed set of dimensions, and produces a quantified report of what remains to make every entity "regular". The report is the deliverable of this story; the accuracy of its measurements must be verified before any remediation work is multi-tasked off the back of it — fixing entities is explicitly out of scope here.

Phased rollout: prove the approach on one pilot component first (ores.refdata — largest, most varied entity population, and the component where the legacy primary-key-heading symptom was found) before running it across the other ~19 components. The pilot validates the dimensions and the tool's accuracy cheaply; only once it is trusted on refdata does it get pointed at everything else.

Classification dimensions (settled)

Grounded in the verified feature/profile catalogue (ORE Studio Variability Model, Variability Features, Variability Profiles) synced before this list was finalised — see the parent task's Notes for the full sync history. Each dimension states what it measures and, where applicable, exactly what the tool reads to compute it:

  • Componentores.refdata, ores.iam, ores.dq, … (every component with codegen models, not a fixed subset).
  • Meta-type — the model type the entity's #+type:=/filename suffix declares (=domain_entity, lookup_entity=/=enum, junction, field_group, component, service_registry; see Applied MASD § "Model types").
  • Profile match — does the entity's actual feature-value combination match one of the 5 named profiles exactly? If not, a feature-by-feature diff against its nearest profile (by Hamming distance over the shared feature set) — this is the dimension that turns "27 loose knobs" into a single comparable signal per entity, and surfaces genuinely novel combinations worth naming as a new profile rather than left as drift.
  • Individual feature values — for entities with no close profile match, the raw value of every feature in the catalogue (tenancy scope via has_tenant_id=/=has_workspace_id, key shape via has_uuid_primary_key, Qt surface via the ores.cpp.qt bundle, SQL tenant-scoping policy via system_scope=/=nullable_tenant_id, etc.).
  • Model format / legacy status — current domain_entity=/org-mode convention vs legacy =lookup_entity vs the legacy top-level Primary key heading (task) vs no model at all (hand-written, uncatalogued).
  • Per-layer coverage — SQL, C++ domain, repository, service, messaging/JSON IO, Qt, HTTP, CLI, Shell, Wt, manual chapter: does the archetype's expected output path exist on disk for this entity.
  • Codegen regen drift — does regenerating the model reproduce the checked-in files byte-for-byte, or has the template moved on since the entity was last regenerated.
  • Hand-crafted vs paste-block discipline — do manual customisations live inside a documented paste-block marker (Paste blocks), or as raw edits to generated files a regen would silently clobber.
  • Compound vs single natural/primary key.
  • Per-layer test coverage.

Status

Field Value
State DONE
Parent sprint Sprint 24
Now Dimensions settled and the classification tool built and verified on the ores.refdata pilot. Closed at sprint 24 health review: rollout to the remaining ~19 components split into Entity classification and drift baseline across all components.
Waiting on Nothing.
Next Nothing – see the rollout story for the remaining components.
Last touched 2026-08-03

Acceptance

  • An automated tool exists (compass command or script) that walks every codegen entity model and its generated/hand-crafted artefacts and computes the classification, with no hand-maintained table.
  • The classification dimensions are settled (see above) and documented.
  • The tool's output is spot-checked against known-good and known-bad entities (e.g. currency as the reference specimen; the 16 primary-key-heading entities as known-legacy) until we are confident it measures drift accurately.
  • The tool and dimensions are proven on the ores.refdata pilot, with a reviewed, trusted pilot report, before rollout to the remaining components (tracked in the split-off rollout story).

Tasks

Task State Start End Description
Settle entity classification dimensions and tool design DONE 2026-07-31 2026-08-01 Review entity_coverage_matrix.org, entity_evaluation_checklist.org, and entity_catalogue.org as input, finalise the classification dimensions (component, tenancy scope, meta-type, model format/legacy status, per-layer coverage, codegen regen drift, hand-crafted-vs-paste-block, compound-vs-single key, variability knobs, test coverage), and design how the automated tool computes each from the codegen models and generated file tree. Dimension coverage must be exhaustive – a missed dimension lets undetected drift accumulate and the codebase degrade again.
Build and verify the classification tool on the ores.refdata pilot DONE 2026-08-01 2026-08-02 Implement the automated classification/drift tool and run it against ores.refdata only. Spot-check its output against known-good (currency) and known-bad (16 primary-key-heading legacy models) entities until confident the measurements are accurate. Produce the refdata drift report.

Decisions

Out of scope

  • Actually fixing/regenerating any entity's drift (this is a measurement story; remediation is multi-tasked afterwards, off the resulting report).
  • Retrofitting a new metatype/facet system into ores.codegen itself.

Emacs 29.3 (Org mode 9.6.15)