Task: Route has_parent_id to the entity root and rebind the entities the defect masked
Table of Contents
This page documents a task in the Fix the has_parent_id feature namespace so profile bindings take effect story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
Route has_parent_id to the entity root, where every reader looks for
it, so a bound profile's assignment reaches the generator. Then retire
the explicit workaround lines the defect forced, and repair the
entities the defect masked.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Fix the has_parent_id feature namespace so profile bindings take effect |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-09-17 |
3. Acceptance
_FEATURE_NAMESPACEmapshas_parent_idto the empty namespace, that is, the entity root.- The four hierarchy models (
business_unit,counterparty,party,folder) carry no explicithas_parent_idline and still generate the hierarchy block. - The eleven flat entities bind
uuid-identified-lookup, carry no explicithas_pagination, and generate no hierarchy block. - Regeneration over the nine known-drift-free components produces no diff.
4. Plan
- Locate every reader of the feature, in
core.pyand in the template library, and record which namespace each one reads. Confirm that nothing readssql.has_parent_id. - Change the one line in
_FEATURE_NAMESPACEthat routes the feature. - Drop the four explicit
:has_parent_id: truelines the profile now supplies. - Survey every model that binds
self-referencing-hierarchyand check each one against the profile's stated contract, the two column properties. - Pick the profile for the entities that fail that contract. Compare the candidates on feature assignments and on the physical-space table.
- Rebind those entities and drop their now-redundant
:has_pagination:. - Prove the whole change is output-neutral by regenerating the nine known-drift-free components and diffing.
- Correct the documents the defect had misled. The feature page, the
feature index, the variability model, and the two codegen meta-model
pages had all filed the feature under
ores.sql.schema.
5. Notes
The reader inventory. Every reader resolves to the entity root. In the
template library, eighteen files read the key, most as bare
{{#has_parent_id}} inside a {{#domain_entity}} section, and the SQL
facet's create template as {{#domain_entity.has_parent_id}}. In
core.py, the hierarchy candidate test and the C++ uuid-include gate
read domain_entity['has_parent_id']. doc_generate.py groups the
feature with has_tenant_id and has_workspace_id at the root in its
hierarchical-composite shape preset. Nothing anywhere reads
sql.has_parent_id.
What the feature gates. The SQL facet emits a recursive-CTE
hierarchy_fn returning flat (id, parent_id, name) rows. The C++ side
gates repository::get_hierarchy, service::get_hierarchy, and the
protocol and NATS-handler entries that reach them.
The two column properties. :parent_id_column: and
:hierarchy_name_field: are read only by the two SQL-facet templates,
yet every model authors them in the root * Flags drawer. Two readers
and one authoring site disagree on the namespace. Moving them into
* SQL would tidy that up, but the reader paths must change in the same
edit. Not done here; the story records it as out of scope.
Why a guard would have helped. The defect's shape is silence. A
profile feature whose value no reader consults produces no error, and
removing the workaround line produced deleted generated code with no
model-level signal. A loader check that fails when has_parent_id is
true and either column property is missing would convert that silence
into a hard error at regeneration time. It would not have caught the
namespace fault itself, but it would have caught the eleven masked
entities the moment the namespace was fixed. Filed as a capture.
The physical-space tiebreaker. uuid-identified-lookup and
self-referencing-hierarchy both carry a * Physical space table
enabling ores.cpp.eventing-integration-test.
uuid-surrogate-lookup carries no such table at all, so rebinding the
eleven to it would have dropped that facet and deleted eleven generated
integration tests. This is what decided between two profiles whose
feature assignments are otherwise interchangeable here.
6. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario, run
through the QA Validation Runner panel) that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
7. PRs
| PR | Title |
|---|---|
| #2090 | [codegen] Route has_parent_id to the entity root so profile bindings take effect |
8. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | Story claimed none of the eleven rebound entities has a natural key; ten declare :natural_key: true. |
story.org | Accepted | Fixed in the Decisions entry. The earlier check searched for the phrase Natural key and missed the property. |
| 2 | Story frontmatter said the one entity whose profile does not describe it; the count is eleven. |
story.org | Accepted | Fixed in #+description. |
| 3 | The predecessor story's sprint row still described the has_parent_id namespace as broken in the present tense. |
sprint.org | Accepted | Reworded in the same commit. |
9. Result
The feature routes to the entity root. _FEATURE_NAMESPACE now maps
has_parent_id to the empty namespace, where has_tenant_id and
has_workspace_id already lived, so a bound profile's assignment
reaches every reader.
One line of code changed; the rest is models and documents. The four
hierarchy models dropped their explicit :has_parent_id: true lines
and still generate the hierarchy block. The eleven flat entities that
had bound self-referencing-hierarchy without the profile's two
column properties moved to uuid-identified-lookup and dropped their
redundant :has_pagination:. The documents the defect had misled were
corrected: the feature page, the feature index, the variability model,
and the two codegen meta-model pages, whose UVL diagrams were
recompiled and re-rendered.
| Check | Result |
|---|---|
| Codegen drift, nine registry components | No drift: regenerated output matches the checked-in tree |
| Site build | 33 pages published, 0 failures |
| Compass suite | 164 passed, 1 skipped |
| UVL diagram recompile | byte-identical to each committed SVG |
Acceptance:
_FEATURE_NAMESPACEmapshas_parent_idto the entity root: met, by the one-line change inorg_loader.py.- The four hierarchy models carry no explicit line and still generate the hierarchy block: met, and proven by the drift gate, which regenerates all nine components and finds no difference.
- The eleven flat entities bind
uuid-identified-lookup, carry no explicit:has_pagination:, and generate no hierarchy block: met. - Regeneration over the nine known-drift-free components produces no diff: met.
The loader guard that would reject the feature without both column properties is not built here. It is filed as a capture, as the story's out of scope records.