Repository navigation
Proposal: typed, directed, trust-bearing relationships — today they are prose #16
Description
Second observation from implementing OKF in Roteiro (see also #15, on imported concepts). This one is about the links between concepts rather than the concepts themselves.
Please correct me if v0.2 has a mechanism here I have missed — I could not find one, but this is the kind of thing a spec can express in a place I did not look.
Problem
A relationship in OKF is an untyped, undirected, untrusted markdown link. Everything a producer knows about the relationship has to be flattened into prose.
Roteiro's graph edges each carry four attributes — kind, provenance, confidence, and the import layer they came from. Rendering to OKF, we currently emit:
## Relationships
### calls
* → [checkout](../functions/checkout.md)
* ← [handler](../functions/handler.md) (confidence 0.85)The relationship type is a markdown heading. The direction is a glyph. Everything else is parenthetical prose. All of it is machine-readable only by a consumer that reverse-engineers our layout conventions — which is precisely the coupling OKF exists to remove, and it is the one part of our bundle that a different producer would encode differently.
Scale, from this repository's own graph: 19,349 relationships across 9 types — calls 10,222, defines 4,652, contains 3,214, imports 967, references 294, and a long tail. An agent asking "what calls this?" has to distinguish a calls edge from a contains edge, and today the only signal is a heading it must parse.
The sharper half: trust stops at the concept boundary
§5.3's tiers describe how much to believe a concept. There is no equivalent for a relationship — so these two render identically:
- a link a human wrote in an architecture decision record, and
- a link an embedding-similarity pass guessed at.
In our graph they are different provenance classes (546 authored edges versus 18,803 derived, in this repository). In the bundle they are both a bullet under a heading. A consumer that correctly refuses to trust an unverified concept has no way to apply the same judgement to an unverified relationship — and relationships are what turn a pile of documents into a graph, so they are arguably where a wrong claim propagates furthest.
Proposal
Express relationships in frontmatter, reusing the trust vocabulary the spec already has rather than inventing a parallel one:
relationships:
- to: ../functions/checkout.md # REQUIRED. a concept in this bundle
type: calls # REQUIRED. producer-defined, like `type` on a concept
direction: outbound # OPTIONAL. outbound (default) | inbound
verified: # OPTIONAL. §5.3 shape, applied to the relationship
- { by: roteiro/5.0.0, at: 2026-09-01T12:00:00Z }
generated: # OPTIONAL. §5.3 shape
by: roteiro/5.0.0
at: 2026-09-01T12:00:00ZThe tier rules of §5.3 then apply unchanged, one level down: a relationship with no verified is unverified, one confirmed by a non-human actor is machine-confirmed, one confirmed by human:<id> is human-reviewed. Nothing new to learn.
type is deliberately producer-defined and unconstrained, exactly as concept type is — the spec's only hard requirement there is that it be non-empty, and the same reasoning applies. Standardising a vocabulary of relationship types across domains would be a much larger undertaking and is not what this asks for.
Not asking for a confidence field. The spec's reasoning against scores — subjective, unportable, goes stale — applies here too, and I agree with it. I mention our (confidence 0.85) only to be transparent that it currently leaks into the body, where it is neither queryable nor governed by anything. Under this proposal we would drop it rather than lobby for it.
Backwards compatibility
- Optional. A bundle without
relationshipsbehaves exactly as today, and body links keep working. - Additive to §5.3 rather than a change: the same
verified/generatedshapes, the same actors (§7), the same tier derivation. - Body links are not deprecated. A producer may write both, and a consumer that ignores
relationshipssees the bundle it sees today. Whether the spec should say anything about keeping the two consistent is worth deciding — my instinct is to say the frontmatter is authoritative where both exist, and say nothing stronger. - Composes with Proposal:
imported— attribute a concept taken from another bundle without inheriting its trust #15 (an imported relationship reports the upstream's tier without inheriting it) and with Proposal: Third trust fieldrefuted#13 (refutedapplies to a relationship by the same rule).
Background
We chose OKF because the trust mapping was, in our ADR's words, "a rename rather than an invention" — our authored/derived/inferred provenance already meant what §5.3's tiers mean. That is a strong endorsement of the concept model, and it is why the relationship gap stands out: the graph we can describe in our own store is strictly richer than the graph we can describe in the bundle, and the part that does not survive is the part that makes it a graph.
Happy to prototype against a draft and report what a real round-trip needs.
Activity
joepietrzak commentedon Sep 3, 2026
@pixie79 I second this, I absolutely think we need directional relationships in OKF v0.3
I implemented a version of this in telamon
This will truly enhance data sharing, which is a stated goal of OKF itself. In the physical world, relationships are typed; in a graph database, relationships are typed, there is no reason to not support this explicitly in Spec. One of the biggest changes in 0.2 was provenance which the industry has confirmed is absolutely the right move. I think a no brainer for 0.3 is the addition of this
andrewcrenshaw commentedon Sep 11, 2026
You haven't missed a mechanism - v0.2 has none, and we hit the same wall from a different direction. Our edges are lifecycle and conflict rather than code structure, and we wrote the case up as GoogleCloudPlatform/knowledge-catalog#148 with registration text in GoogleCloudPlatform/knowledge-catalog#195. That work belongs here now, not there, so read this as the proposal moving rather than a second one.
One thing we'd add to your shape. A
typethat's producer-defined and unconstrained is machine-readable but not machine-actionable: a consumer readingtype: supersedesstill doesn't know whether to drop the target from an in-force query. We'd keep your carrier exactly as you've drawn it and register query-time semantics alongside specific types, so the two travel together:supersedes- asymmetric, points backward in time. Query-time: exclude the superseded concept from in-force retrieval, retain it for lineage.contested_by- symmetric. Query-time: surface both and defer adjudication to the consumer. Carries no verdict by design.The invariant we'd want in the same clause, because it's what your
verified/generatedon the edge makes possible: exclusion follows affirmation. An automated writer may propose a supersession; the incumbent keeps governing until an appended, attributed resolution event puts it in force. With 18,803 derived edges against 546 authored, you need that rule more than we do - a similarity pass shouldn't be able to retire a concept by asserting an edge. Your proposal supplies the provenance the rule depends on, which is the part ours was missing.Both keys ship in our exporter. @ajdelaguila carries the same two in Data Olympus independently. The two systems differ on one mechanism (GoogleCloudPlatform/knowledge-catalog#195, 5 Sept): Data Olympus holds
contradictsas annotation that never filters, so a contest-to-supersession count means reading git diffs, and we append a resolution event at settlement, so the same count is a query.Two smaller notes. Targets should key off a stable concept id per GoogleCloudPlatform/knowledge-catalog#120 rather than a path, or a file move silently reattaches an edge to the wrong incumbent. And a dangling target is not an error - if the referenced concept is absent from the bundle, the carrying concept is current.
Happy to restate the GoogleCloudPlatform/knowledge-catalog#195 registration text against your frontmatter shape and put it up here, or to review yours if you get there first. Either works from our side.
ajdelaguila commentedon Sep 12, 2026
Data Olympus implements source-gated supersession over concept ids.
supersedesandsuperseded_byare frontmatter ids rather than paths, and an in-force query excludes any document that is the target of asupersedesedge whose source is itself in force. An edge asserted from an inbox document excludes nothing whatever status it claims, and a dangling edge excludes nothing either, because the exclusion join requires both ends to resolve.That is a weaker guarantee than the invariant named above, and the difference belongs in the spec rather than in any one implementation. Source eligibility says the edge comes from something currently governing; it does not say anyone affirmed this particular retirement. So if the carrier holds
verifiedandgenerated, the registration should distinguish provenance metadata on an edge from the attributed resolution that authorizes exclusion, which is the distinction a consumer needs when 18,803 of 19,349 edges are derived.On the mechanism named above,
contradictshere is annotation that never filters, and recording a contest disposition is open at knaisoma/data-olympus#241. Glad to review the registration text restated against this carrier.andrewcrenshaw commentedon Sep 12, 2026
Registration text is up as #22, restated against this carrier rather than the flat keys it used before.
@ajdelaguila your source-eligibility point is the spine of it. The three rungs are separated there and named: edge provenance on the relationship, source eligibility of the asserting concept, and the attributed resolution that authorizes exclusion. Only the third excludes, and rung 2 is written in as the weaker guarantee a shipping implementation actually runs rather than folded into rung 3.
@pixie79 it registers two types and touches nothing about the carrier. If you would rather the carrier and its first two registered types land together, say so and we will fold it into #16 instead.
pixie79 commentedon Sep 13, 2026
Fold or keep separate — keep #22 separate, please.
The carrier and the registry are different kinds of claim and I think they should be reviewable independently. #16 argues a shape can carry what producers already know; #22 argues what a consumer must do with two specific types. A maintainer could reasonably accept the first and defer the second, and folding them removes that option. #22 also reads well standing on its own, which is the better test.
@ajdelaguila's three rungs are the right correction and I'd rather not have the carrier claim more than it earns. To be explicit about my side: our edges carry
kind,provenanceandconfidence, and none of that is an affirmation. 18,803 of our 19,349 edges are derived; if edge provenance alone authorised exclusion, a similarity pass could retire a concept here. So rung 1 is all the carrier should be read as supplying.Two things I can now offer as measurement rather than opinion.
Stable ids over paths — agreed, and we have the numbers. We tried deriving a concept's path from its key and it fails quietly: a path depends on the whole placed set (nesting, plus a disambiguating digest when two keys slug alike). On a real render it guessed wrong for 43 links, each a valid-looking path to a file that did not exist. We now resolve every link through a
key -> pathmap built after placement. That is the same reason your "targets key off a stable id" note is right, arrived at from the other end.Where I cannot yet help. We do not populate author fields, and our
sourcesentries carryresourceonly — our writer emits nothing else (crates/rto-render/src/okf.rs:268-273) and our reader currently discards a peer'stitleandauthoron import (crates/rto-render/src/okf/read.rs:620-624). So if the registration depends on attributing a resolution to an actor read out of someone else's bundle, our implementation is not yet evidence either way. I would rather say that than imply coverage.Happy to review the registration text as it stands in #22.
andrewcrenshaw commentedon Sep 14, 2026
Keeping them separate, agreed, and your reason is better than ours was. A maintainer being able to take the carrier and defer the registry is worth more than the convenience of one thread.
Your rung-1 cap is the part we would not have been able to state for you. The carrier's own author saying
kind,provenanceandconfidenceare not an affirmation settles what #22 can lean on, and 18,803 derived against 546 authored is the number that makes it concrete rather than cautious.The 43 links are now in #22. Three of us have arrived at stable ids from different directions - your path-from-key guessing valid-looking paths to files that do not exist, our resolution events surviving a move, and @3a3 on #26 needing paths that re-derive identically across parts. Yours is the only one of the three that comes with a count.
On the author fields: that limit shaped the revision rather than sitting outside it. #22 now says a resolution entry with a missing or unparseable actor is not a readable affirmation, so the incumbent stays in force and nothing is excluded. Roteiro excludes nothing under that rule and needs no change to stay conformant, which is the right answer for a producer that has not chosen to carry actors rather than a gap it has to close first.
Review of #22 whenever it suits. @ajdelaguila's has already reshaped it.
mlnrt commentedon Sep 17, 2026
I support the idea. My current addition to OKF v0.2 is following:
ajdelaguila commentedon Sep 17, 2026
Data Olympus carries these as frontmatter edges keyed on concept ids rather than paths.
supersedes,superseded_byandcontradictseach name the target document'sid, the linter warns when a value is path-shaped, and for the two supersession keys a target that resolves to nothing is an error that blocks CI rather than an edge that silently retires nothing.Worth keying your
to:the same way before the shape settles. A path names a location rather than the thing at it, so a rename reattaches or dangles the edge without anything in either file changing. pixie79 put a number on the same root cause earlier here: deriving link paths from keys guessed wrong 43 times in one render, each a valid-looking path to a file that did not exist. Different trigger, same reason, since a path depends on context outside the two files it connects. Yourenforced_byedge already points at/scripts/validate.py, so a path-shape check and an unresolved-target check are cheap to add there.deepdb-ch commentedon Sep 21, 2026
Writing from the Property Graph Markdown project: the separation emerging here between a relationship carrier (#16) and type-specific query behavior (#22) is exactly the boundary PGM 0.4.0 is designed around.
PGM 0.4.0 Public Draft 1 is an external semantic profile of OKF 0.2, CommonMark, and YAML. It does not define a relationship vocabulary or give
calls,supersedes, orcontested_byapplication semantics. It defines how one exact relationship occurrence, its direction, properties, and optional type are carried without adding Markdown syntax.For the example in this issue, the source form is an ordinary concept link:
PGM interprets this as one directed relationship occurrence from the current concept to
../functions/checkout.md. The complete YAML flow mapping is retained as the relationship property map. A non-empty stringtypeis additionally exposed as the graph-element type, but remains present in the properties. Thegeneratedandverifiedvalues above are therefore carried without PGM assigning them any trust or exclusion semantics; OKF or a vocabulary profile can define those semantics independently.This gives a few compatibility properties that seem relevant to the design choices in this thread:
direction: inbounddeclaration in the current document would therefore be outside PGM Core.The proposed frontmatter
relationships:list can still be useful as a normalized projection or index, especially for consumers that do not want to scan Markdown bodies. The important interoperability question is whether it is authoritative source or derived projection. Making both the inline link and the frontmatter entry independently authoritative creates a synchronization problem and makes exact link occurrences ambiguous. PGM deliberately keeps the metadata attached to the link occurrence that asserts the relationship.PGM does not solve the separate stable-concept-ID question raised above. It follows the pinned OKF 0.2 concept/path model; its portable relationship keys and occurrence IDs are deterministic and bundle-relative, but change when a source ID, target ID, or property map changes. A future OKF stable-ID mechanism can be composed with the carrier without changing its occurrence semantics.
The public draft includes a reference processor, executable conformance tests, deterministic JSON/Cypher projections, and a 46-concept/124-relationship fixture. An opt-in NornicDB adapter is also being implemented in orneryd/NornicDB#390.
If useful, the PGM project can contribute a compact interoperability fixture for this issue: the same Roteiro-style relationships represented as PGM source, expected Core/JSON output, and a deterministic projection to the proposed
relationships:list. That would let the carrier and the frontmatter index be compared before either is made normative.andrewcrenshaw commentedon Sep 21, 2026
contested_byis the deprecated spelling as of last week. #22 (query-time semantics forsupersedesandcontradicts) registerscontradictsas the stored key,contradicted_byas the derived view that is never written to frontmatter, andcontested_byas deprecated. We shipcontested_bytoday and have the migration to do, so the example still matches a real bundle, ours.One record authoritative, the other derived. Whether the frontmatter list is source or projection is the same trade we ruled on #22 for the other axis: a mirror write, with both records carrying the edge, is a two-write that can half-apply. We store one direction and derive the reverse at read time, and @jpavley's production evidence on inverted edges is what settled it. The same test on inline-versus-frontmatter puts the assertion on the link occurrence and makes the frontmatter list an index over it. Two independently authoritative records of one relationship is a synchronization problem whichever axis it runs on.
Separately, and not about this thread: your normative OKF baseline pins
okf/SPEC.mdin knowledge-catalog, which is the frozen snapshot and predates #6's explicit-offset requirement. #24 is the live thread on whatokf_version: "0.2"now names, with two implementations there reading it opposite ways.The interoperability fixture would be useful, and the projection is the part we would reach for: the same relationships as PGM source, as a #16
relationships:entry, and the deterministic mapping between them. #22 acts at query time on whatever the carrier delivers, so a carrier with a defined projection is one we can evaluate against rather than guess at. We're glad to supply thesupersedesandcontradictsside of it from our bundle if that helps.deepdb-ch commentedon Sep 22, 2026
Thanks — three useful points of convergence, and one correction on my side.
First, I should have written
contradicts, notcontested_by. In the fixture,contradictsshould be the stored predicate,contradicted_bya derived view that is never serialized, andcontested_byat most a deprecated-input case.Second, agreed on authority: a PGM link occurrence is the assertion; a
relationships:entry should be a deterministic projection of that occurrence, never a second independently authoritative record. That gives us a testable mapping without introducing a two-write synchronization problem.Third, the PGM baseline pin is intentional. PGM 0.4.0 Public Draft 1 normatively identifies the exact OKF commit
3fcbb9f…and its SHA-256, so this release does not silently absorb later changes from a movingmain. You are right that the pinned text predates #6’s explicit-offset requirement. I therefore read #24 as input to a future, explicitly versioned PGM baseline revision—not as something that should retroactively change 0.4.0. We can make that boundary more visible in the fixture documentation.I would welcome the
supersedesandcontradictscases from your bundle. A compact fixture could contain the same assertions in four views: PGM Markdown source, expected PGM reference JSON, deterministic #16relationships:projection, and the derived query view. It should also cover an untyped link, repeated equal occurrences, an unresolved target, and verify thatcontradicted_byis derived rather than stored.If that scope works for you, the PGM project can prepare the carrier and projection sides while you supply the two vocabulary-specific cases.
mlnrt commentedon Sep 22, 2026
@deepdb-ch @andrewcrenshaw the prose vs frontmatter authoritative record and the risk of drift is an issue. In our Agentic spec driven development framework, I basically took the total opposite direction than you @deepdb-ch with PGM. Reference links inside the artifact are prose (e.g. "specification document xyz states that...") without the link. The relationships/links are all in the frontmatter.
Going forward, I am curious if at this point OKS maintainers are considering this
relationshipskey proposal for future version or not at all?andrewcrenshaw commentedon Sep 22, 2026
That scope works. We can supply both cases from the published bundle at
3806111, which is the commit @leesharks000 ran the cross-implementation test against, so the inputs come with a third-party reproduction behind them.What the bundle emits today, keyed on stable ids rather than paths:
Two things follow from that.
contested_byis the exporter's current output, so the concept is an actual instance of the deprecated-input case rather than a hand-written stand-in for one, andcontradictsarrives with the exporter migration. Neither target resolves to a concept in the bundle either, so the same file carries your unresolved-target case as real producer output: under #22 the carrying concept stays in force and nothing is excluded.The fourth edge case is the one worth keeping prominent. Whether
contradicted_byis derived rather than stored is what decides if a consumer can round-trip the registration at all, and a fixture is where that stops being a claim in prose.On the pin: the exact commit, its SHA-256, and the MUST against substituting a moving branch already close the drift question, and #24 is an argument about what a version string names rather than what a hash names. An explicitly versioned baseline revision is the right place for the offset change to land.
One for @pixie79 rather than for us. If a
relationships:entry is a deterministic projection of the link occurrence, that is a different authority model from the carrier as drafted, where a producer writes the list directly and Roteiro emits it from its own graph. Worth settling with him before the projection side goes into the fixture.andrewcrenshaw commentedon Sep 22, 2026
Three routes to the same requirement, and they agree more than the framing suggests. PGM puts the assertion on the link occurrence and derives the frontmatter list. Your framework keeps links out of prose, so there is no second record to drift against. #16 as drafted has the producer write the list directly. All three end at one authoritative record per relationship and differ on where it lives, and none of them allow two independently authoritative copies of one edge. That constraint is the part worth carrying into whatever the carrier becomes.
On the maintainer question, the observable state rather than a reading of it. The last commit here is
ad30107on 21 August, the merge of #6. Five community PRs are open from early September (#17, #18, #21, #23, #25) with no review on any of them, and the only comments on them come from the CLA bot. #19 was closed by its own author rather than by a maintainer. No maintainer has commented on a community proposal in this repo, and the nearest precedent, GoogleCloudPlatform/knowledge-catalog#303, has been open since 17 August.That is the state and not a forecast. What it argues for is converging in the open first, so that whatever does get reviewed arrives with one shape behind it rather than four. The past week has mostly gone that way: #30 folded into
relationships:, PGM defines a projection onto the carrier rather than a rival to it, and #22 sits above it on two predicates.deepdb-ch commentedon Sep 22, 2026
That contrast is precisely why PGM deliberately does not introduce a frontmatter relationship list.
A
relationships:block uses YAML, but OKF would still need to define an additional relationship-record schema: fields such asto,type, direction and provenance, plus identity, occurrence and synchronization rules. Where the prose already contains the link, the relationship must then either be maintained a second time in frontmatter or one representation must be declared derived.PGM instead reuses two existing syntaxes without adding a new Markdown construct or a relationship-specific property language:
type.This makes the PGM representation deliberately sparse: one relationship occurrence, one location and one authoritative record. A frontmatter
relationships:list can still be generated as an index or projection, but it need not become a second authored representation.Your frontmatter-only design is internally consistent because the prose intentionally contains no links, so it avoids duplication by choosing a different source of truth. The trade-off is that the semantic assertion no longer resides where the human-readable reference occurs. PGM chose inline, in-place enrichment because it preserves that locality, requires less additional specification, and degrades gracefully to ordinary Markdown.
That is the architectural distinction the interoperability fixture should make explicit: PGM relationships are asserted at link occurrences; a frontmatter list, when present, is a derived projection rather than the semantic source.
andrewcrenshaw commentedon Sep 22, 2026
One constraint on the inputs we offered, since it decides how those two cases sit in that frame. The bundle at
3806111carries no prose links for them at all.supersedesandcontested_byare frontmatter keys on concept ids, written by the exporter, with no link occurrence anywhere to project them from. Same shape as @mlnrt's, reached from the generation side rather than the authoring side.So for the two vocabulary cases the four views do not stack into one chain. There is no PGM source to derive them from unless one is written for the fixture, and a synthesized source would turn those rows into a demonstration rather than production output, which is the thing they are there to supply.
Naming the producer's authoring mode per case would hold both without either taking the other's ground: PGM-native assertions projecting to a
relationships:index, and frontmatter-native output where the frontmatter is the record. Both ship today, and a consumer meeting an OKF bundle in the wild will meet both.mlnrt commentedon Sep 22, 2026
@pixie79, @deepdb-ch, @andrewcrenshaw in the relationship proposal, if directions is outbound only like PGM: How do you plan to deal with for example with the case of one of the relationship being pointed at being deleted? Because we now have a broken link that can't be cleaned up when that artifact is deleted since we do not know what is referencing it and searching the entire corpus for artifacts referencing the one we are about to delete does not scale.
deepdb-ch commentedon Sep 23, 2026
@mlnrt Good question. In PGM, outbound describes where an assertion is authored, not how incoming references are queried. A consumer can maintain a derived reverse index from target concept ID to source document and link occurrence. When a source changes, it updates that document’s index entries. Before deleting a target, it queries the index and visits only the sources that actually reference it. Building the index initially requires a corpus scan; each deletion does not.
PGM does not prescribe the deletion policy. An application can block deletion while references exist, retain unresolved relationships, or update the referring documents as an explicit migration. PGM Core does not silently remove source links when their target disappears. An outbound-only frontmatter list needs the same reverse lookup; placing the assertion in frontmatter does not by itself provide an inbound index.
deepdb-ch commentedon Sep 23, 2026
@pixie79 Your
handlerexample makes the property-carrier question concrete. PGM 0.4.0 can move the prose annotation onto the existing link occurrence:A PGM-aware consumer reads the YAML flow map in the Markdown link title as properties of that specific relationship. The same map can carry an optional
type, provenance, import layer, or nested values—without a separate frontmatter relationship record. That is the property-graph characteristic: the relationship itself carries properties, rather than being only an unannotated triple.This does not ask OKF to standardize confidence scores. PGM neither requires
confidencenor assigns it trust semantics; Roteiro can omit it if scores are not portable.One direction caveat:
←remains prose, not a PGM direction operator. In PGM Core, the link above asserts this document → handler. If the intended assertion is handler → this document, the authoritative link belongs inhandler.md; this line can remain a derived backlink display.andrewcrenshaw commentedon Sep 23, 2026
The premise worth testing first is whether a stale edge needs cleaning up at all. #22 rules that it does not: if the target is absent the carrying concept is current, and a dangling edge excludes nothing, because the join needs both ends to resolve. Under that rule a deletion leaves no repair owed on any referrer, and the corpus scan you are pricing drops off the critical path.
What the deleted end owes instead is a record at the target's own id, in the machine index rather than in prose. Ours is published, and @leesharks000 confirmed it consumer-side against the artifact before we shipped it (#11):
A consumer resolving a target that is no longer there reads one entry keyed by the id it already holds, and learns whether the concept was removed or never landed, and for a removal where it went. That is a lookup at the target rather than a search for referrers, and it separates a deletion from a typo, which a broken link cannot do on its own.
@deepdb-ch's reverse index is what you need to notify or migrate referrers, and that is a policy choice rather than a correctness requirement. The two compose: the absence record makes a stale edge safe to leave, the index makes it findable when you want to move it.
Neither the carrier nor the direction field answers deletion, and your question is what puts that in the open. Glad to put the absence-record shape alongside the two vocabulary cases in the interoperability fixture if it earns its place there.
leesharks000 commentedon Sep 23, 2026
an ontology that deletes its own deletions is running blind
deepdb-ch commentedon Oct 2, 2026
@pixie79, your Roteiro example shows why a relationship needs its own trust signal. Suppose Roteiro infers that
checkoutcallshandler. Incheckout.md, PGM records the claim on the link itself:This records who produced the relationship, not that anyone checked it. With no
verifiedevent, the relationship is unverified—even if thecheckoutconcept itself is human-reviewed.If an automated check confirms the call, the link is updated and becomes machine-confirmed:
If Alice subsequently verifies it, both checks remain recorded. Because one verifier is human, the relationship becomes human-reviewed:
These are successive revisions of one authored link, not three relationship records to keep in sync. The verification stays with the assertion it concerns.
PGM Core preserves these YAML properties without assigning a trust tier. The optional PGM OKF Relationship Trust Profile v1 applies OKF's three-tier derivation to each relationship occurrence. A PGM consumer may preserve
verifiedwithout deriving a tier; a processor claiming the profile derives the advisory tier from it. The executable example tests all three tiers.Would this preserve the distinction you need between a relationship Roteiro inferred and one that has actually been checked?
DavidROliverBA commentedon Oct 2, 2026
One measured consequence of the dialects coexisting, for whoever weighs the carrier.
We ran two shipping OKF extensions against each other (E9). KnowledgeX writes
supersedes:andcontradicts:as top-level lists of file names; AI-XF writeslinks: [{rel, to: <id>}]. Both bundles are valid OKF, and each tool checks the other's without errors. But each tool's maintenance checks then report the other's retired concepts as "deprecated without a successor", and AI-XF counted a KnowledgeX contradiction as zero open contradictions. Nothing fails, so nothing tells you.That is an argument for a carrier landing before the dialects multiply further, and for keying
toon ids, as @ajdelaguila suggests: KnowledgeX's own docs note that an editor rename updates body links but not the path-valuedsupersedeskeys.deepdb-ch commentedon Oct 3, 2026
@mlnrt @andrewcrenshaw think we should follow the same principle as OKF here: the relationship semantics themselves should not require referential integrity. OKF explicitly allows links to missing concepts, and PGM relationships likewise remain syntactically valid even if their target cannot currently be resolved.
Referential integrity is then a concern of the consuming application rather than of the relationship representation itself. Applications that need stronger guarantees can implement them using tombstones/absence records, reverse indexes, deletion policies (restrict/cascade/delete), or similar mechanisms.
This keeps the core semantics simple and interoperable.
deepdb-ch commentedon Oct 11, 2026
@andrewcrenshaw Thank you for the bundle and for clarifying that its
supersedes/contested_byassertions have no prose links. The executable PGM ↔ #16 interoperability fixture is now published, with tests and expected outputs.For the link-native case, it provides the Markdown source, exact PGM reference JSON, a deterministic projection into the proposed
relationships:list, and a trace from each PGM occurrence ID to its list index. Its four projected entries match the independently authored frontmatter example on the #16 fields. Repeated identical links remain separate occurrences. The projection explicitly reportsconfidenceas omitted, since the draft list has no field for it; it does not claim a lossless conversion.Your commit-pinned
rememberconcept and root log are included verbatim and separately from our clearly labeled synthetic PGMsupersedes/contradictsexample. Because your original is frontmatter-native and contains no PGM link assertions, its PGM-link projection is correctly empty. The informative #22 query preview reads itscontested_byas the deprecated input spelling ofcontradicts;contradicted_byappears only as a derived reverse view in the resolved synthetic case, never as a stored assertion. The two targets in your pinned concept do not resolve, so that input produces no exclusion or reverse view. This previews the open #22 proposal; it is not an adopted OKF rule.One concrete gap remains: this #16-shaped projection emits a relative Markdown path in
to, whereas the #22 use case needs a stable concept ID. The synthetic query example uses an explicit path-to-ID lookup, but we do not yet claim a portable resolver or full #22 interoperability.Would you check whether the two authoring modes and their expected outputs reflect the carrier boundary you had in mind—especially duplicate occurrences and stable-ID resolution? The README lists the exact commands and limitations.
mlnrt commentedon Oct 13, 2026
Cross-linking #32, since it proposes something the
relationshipslist here would need as well.#32 is about lists read across a trust boundary: a concept one team publishes, read by another team's agents, whose references include material that reader is not allowed to see. Silently dropping those entries makes the list look complete when it isn't, which misleads any trust judgement made from it. #32 proposes one marker per list, as its last entry:
The party serving a partial view MUST emit the marker whenever it removes an entry, and a consumer SHOULD show it. The marker carries no other key, so it has no to and no type.
#32 was written for sources, but the same problem applies here: a
builds_onorsupersedesedge whose target is internal, where the target id can itself be sensitive (incident-2026-09-01--…).andrewcrenshaw commentedon Oct 13, 2026
The authoring-mode boundary is the one we meant. The frontmatter-native source stays verbatim and separate, its PGM-link projection is empty rather than synthesized, and the pinned files match our
SHA256SUMSat3806111.That pin predates three exporter changes, and the bundle's current commit gives the fixture two cases
3806111cannot. At500ff25d6f79ea0160771b3f4cda5762dee08ed6the concept storescontradictswith nocontested_by, and bundle-rootlog.mdcarries an attributed resolution in the shape #22 registers:The concept file hashes to
124116df0e3745101bf0c630366fd58d73ac4b107ff1a66e86b2f5d0b55acc0candlog.mdtoa1f0a09c00e3c8f8cba7677925ae7a7318051c6128b3f4acb7e599f235e88883. Keeping3806111as the deprecated-input case and adding500ff25as current key plus affirmation would cover both. The predecessor is still absent, so the affirmed case still excludes nothing: it shows a readable affirmation with nothing to remove.Two things in
query_view.pythe newer pin would exercise. It readscontested_byby name, so it would needcontradictsas the stored field withcontested_byas deprecated input. And_root_log_has_resolutionmatches any Supersession entry, where #22 keys on the pair: an entry counts for this edge only if it names this source, this target and an actor. The entry above parses with a reader built from the #22 example alone.Duplicates. Separate occurrences in the projection are right. #22 decides on the pair, so several identical
supersedesoccurrences carry evidence and still produce one in-force answer.Stable ids.
stable_id_by_pathis the resolver #22 assumes, where "a reverse index over stable ids is what resolves targets at all". Within one bundle that is portable: a path maps to the target document's stable id, a target with no stable id stays unresolved and excludes nothing, and on #30 we proposed treating an id that resolves to two concepts the same way. Across bundles it needs a bundle identity, which none of the proposals defines yet.deepdb-ch commentedon Oct 16, 2026
@andrewcrenshaw Thank you for the precise review. I’ve published the corrected interoperability fixture and regression tests.
The
3806111Remember extract remains a separate, byte-verified deprecated-contested_byinput. The new500ff25extract is also kept verbatim and separately: it storescontradictsand includes your attributed bundle-rootSupersessionentry. Both frontmatter-native sources still have no PGM link occurrences to project.The informative query preview now applies Remember’s explicitly documented
remember://lesson/<id>form before joining its bare frontmatter IDs to the log. A supersession entry counts for an edge only with a valid date heading, the exact ordered source–target stable-ID pair, and a readable actor—not merely because some resolution marker appears in the bundle. The500ff25affirmation is therefore recognized for its pair; the predecessor is absent, so nothing is excluded. Tests also reject unrelated, reversed, malformed, and non-root entries for that pair.For duplicates, the PGM carrier and candidate
relationships:projection retain each link occurrence. A regression test creates two equalsupersedesoccurrences and checks that the query preview makes one decision for their resolved stable-ID pair and type, with both occurrence IDs retained as evidence. Missing or duplicate stable IDs remain unresolved and cannot cause exclusion.This is still a narrow preview of the open #16/#22 proposals, not a claim of OKF conformance: source eligibility, conflicting dispositions, and cross-bundle identity remain outside the fixture. Does this now capture the occurrence-versus-pair boundary you intended?