DR-125: scope_tag is mandatory at promotion, so the taxonomy topic grain is transitional
DR-125 — scope_tag is mandatory at promotion, so the taxonomy topic grain is transitional
Section titled “DR-125 — scope_tag is mandatory at promotion, so the taxonomy topic grain is transitional”Context
Section titled “Context”The S528 census could not rule on primary_domain / primary_subtopic because every
route into the question dissolved into a prerequisite. S529’s lane A1 found the anchor the
census had missed entirely: the pair mints the identity of topic concepts in the OKF
bundle — l_records.py:926 writes topics/{domain}--{subtopic}.md, and BI-2 makes
rel_path the concept’s identity, so renaming it mints a different concept. The S528
lane 1 report contains no reference to l_records, ConceptKey or topic concepts across
its 506 lines.
But that anchor is the fallback grain, not the primary one. l_records.py:212-218
describes domain verbatim as “topic locator (fallback grouping) … for scope-tag-less
q_a_pairs clusters”. The primary grain is scope_tag — which
reference/entity-glossary.md:17 names as the q_a_pair relevance mechanism: “Relevance is
computed at query time via scope_tag overlap, not a scoping FK.”
Whether the fallback is transitional or permanent turned entirely on one unanswered
question: does the ratified model intend every promoted q_a_pair to carry a scope_tag?
q_a_pairs.scope_tag carried no promotion rule from any ratified source, and lane A1
correctly recorded it UNDECIDABLE rather than guessing. (Corrected S531: the column is
text[] NOT NULL DEFAULT '{}', not nullable as this section first recorded — so the
enforcement predicate is NON-EMPTY (array_length(scope_tag,1) > 0), not SET NOT NULL.
The ruling is unchanged; only the mechanism reads differently. Measured against Platform
staging: 134 of 143 published pairs empty — synthetic data, recorded as shape not
evidence.)
Decision
Section titled “Decision”Every promoted q_a_pair must carry a scope_tag. It is a requirement of promotion,
not an optional enrichment.
It follows that the (primary_domain, primary_subtopic) topic-concept grain is a
transitional fallback whose requirement expires at first bundle publication, not a
permanent part of the concept model.
Alternatives considered
Section titled “Alternatives considered”- Leave
scope_tagoptional. Then the domain/subtopic pair is permanently load-bearing for bundle concept identity and needs a real enforcement mechanism in its own right — which the schema has never had (zero FK, zero CHECK, zero trigger on any taxonomy vocabulary column;reference_items.layeris the sole counter-example and carries a real validating trigger). Rejected: it entrenches a grain the ontology work is replacing. - Defer behind a dedicated spike. Rejected: the question was already fully framed by A1’s measurement, and deferring would have left id-412 AC-10, id-414 and id-415 parked for another cycle.
Consequences
Section titled “Consequences”- The subject axis still mints concept identity until the fallback is gone, so the
write-side contract must be fixed now rather than skipped as doomed. That work is
id-419, which also carries a safety defect (
validateDomainsilently rewrites an out-of-taxonomy domain tovalidDomains[0], measured assecurity, at full LLM confidence) and the inert enumeration guard (AND sd.primary_domain IS NOT NULLover aNOT NULL DEFAULT 'unclassified'column, which cannot exclude a row at any corpus size). - Promotion needs an enforcement point for the
scope_tagrequirement; without one this ruling is a convention, and DR-104’s lesson is that conventions unenforced by a gate regress. - This does not by itself retire the columns. id-412 AC-10 / id-414 / id-415 stay parked until the fallback is actually removed — the filter question is settled, the columns are not yet gone.
- The measured sentinel defect (
topics/compliance--unclassified.mdin a staging replay) is latent, not shipped: the mintedcanonical-okf-showcasebundle holds four clean topic identities and nounclassified.
(S531 amendment, owner-ruled: the canonical-okf-showcase publication SATISFIES the
“first bundle publication” expiry clause — the question of whether it meant a client
bundle was put to the owner and ruled. The fallback grain was deleted the same session
(48821e6d8: l_records enumeration + ConceptKey fields + the ?domain=&subtopic= URI
form on both sides), which also removed the inert enumeration guard by construction.
Consequently the parking condition on id-412 AC-10 / id-414 / id-415 — “until the
fallback is actually removed” — is now MET; those tasks unpark. The write-contract fix
landed as id-419; scope_tag implementation is id-422.)