Skip to content

A predicate is named one way - #536

Merged
WaylandYang merged 3 commits into
devfrom
feat/a-predicate-is-named-one-way
Sep 9, 2026
Merged

WaylandYang merged 3 commits into
devfrom
feat/a-predicate-is-named-one-way

Conversation

@WaylandYang

Copy link
Copy Markdown
Contributor

The Properties rail read like four different projects. In one knowledge base with
schema.org loaded:

shape rows
acceptedAnswer 3819
owns 966
ApplicableCertificate 60
access to 88

Scrolling that column, accessModeSufficient sits next to access to and the
second one looks like a mistake.

The rule

Classes are UpperCamelCase, predicates are lowerCamelCase. That is the RDF/OWL and
schema.org convention, and it carries information: the case tells you whether a
term is a class or a property.
The library already followed it — 2774 of 2777
classes are UpperCamel (the other three are schema.org's own 3DModel, which
starts with a digit and is correct), and 3800+ predicates are already lowerCamel.
So this is a 148-row correction, not a rewrite.

Changing label is safe because it is never identity. 4875 predicates carry an
iri; RDF export uses the iri, or mints one from key when there is none. No
export path reads the label. key was already normalised to snake_case — for
4996 of 4999 rows it differs from the label only in case and separators.

Only the wrong ones, and never from key

Deriving the label from key would look tidy and would be wrong: to_key does not
insert an underscore between consecutive capitals, so productID becomes
product_id, and rebuilding gives productId. The acronym is gone.

So the migration touches exactly two things and never the inside of a word:

  • a label with a separator becomes camel humps: access toaccessTo
  • a label starting with a capital loses just that one: ApplicableCertificate
    applicableCertificate

Checked against the data first: of the 88 labels with separators, zero contain a
run of capitals; of the 60 starting with a capital, none start with two. So neither
rule can damage an acronym here. productID, hasLEI, accessibilityAPI and
checkoutPageURLTemplate come through untouched.

Those 60 UpperCamel predicates all come from unece.org, and their label is
faithfully the IRI's local name — the vocabulary is inconsistent with itself
(brandName lives in the same namespace). Diverging from its local name is
deliberate; the iri keeps the truth.

New labels are normalised at the three write paths in ontology.rs
(create_relation_type, create_relation_types_bulk, update_relation_type), so
an import or a rename cannot put a spaced label back.

A fact row is a sentence, not a vocabulary

Li Si — worksFor — Meridian Systems reads like code. So the surfaces that read as
prose — the fact row and the entity timeline — split the predicate back into words
at render time (predicateText.ts). The ontology surfaces keep camelCase, because
there you are looking at the term itself and acceptedAnswer is what you would
search for in schema.org's docs.

Acronyms stay whole there too: productID renders as "product ID", not "product
id", and checkoutPageURLTemplate as "checkout page URL template". Facts are also
sorted by the rendered form, so the order matches what is on screen.

Checked

  • cargo build and pnpm build clean; style guard 46/46.
  • Five unit tests on the normaliser cover separators, the leading capital,
    acronyms, already-correct input, and idempotence.
  • Migration run against a 4999-predicate knowledge base: two shapes remain,
    lowerCamel 3967 and single lowercase words 1032. Zero with separators, zero
    starting with a capital, and all 78 acronym labels still intact.
  • In the browser: the rail reads accessModeSufficient / accessTo /
    accommodationFloorPlan in order, and the entity panel shows "subject of",
    "advocated for", "branch of" with no camelCase left in it.

🤖 Generated with Claude Code

WaylandYang and others added 3 commits September 9, 2026 16:32
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
@WaylandYang
WaylandYang merged commit dd71624 into dev Sep 9, 2026
4 checks passed
@WaylandYang
WaylandYang deleted the feat/a-predicate-is-named-one-way branch September 9, 2026 08:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant