Skip to content

okf: propose typed relationship edges (supersedes, contested_by) (#148)#195

Open
andrewcrenshaw wants to merge 2 commits into
GoogleCloudPlatform:mainfrom
andrewcrenshaw:okf-typed-relationship-edges
Open

okf: propose typed relationship edges (supersedes, contested_by) (#148)#195
andrewcrenshaw wants to merge 2 commits into
GoogleCloudPlatform:mainfrom
andrewcrenshaw:okf-typed-relationship-edges

Conversation

@andrewcrenshaw

Copy link
Copy Markdown

Adds okf/proposals/typed-relationship-edges.md: a self-contained proposal for two optional cross-concept lifecycle edges, in the same proposal-doc form as #159's reliability.md. Core spec untouched.

What this adds

Two optional frontmatter keys for typed relationships between whole concepts, each carrying its query-time semantics so a consumer knows not just that a relationship exists but what to do with it:

  • supersedes - asymmetric. Once affirmed, exclude the superseded concept from in-force retrieval; retain it in the bundle for lineage.
  • contested_by - symmetric. Surface both disputing concepts and defer adjudication; never resolve the edge as a verdict. (contradicts is a back-compat alias.)

Both are additive under section 4.1 and keep a bundle valid under section 9. Untyped consumers preserve the keys on round-trip and see ordinary linked concepts; typed-aware consumers apply the semantics.

Why it's shaped this way

This is the consolidation of a multi-producer convergence on #148 and #158. Three independent production implementations - Lexenne remember, @inkxel's Throughline, and @ajdelaguila's Data Olympus - landed on close-but-not-identical shapes for the same two edges. Rather than bless a spelling, the proposal registers the two edges with their query-time semantics attached, which is the part a consumer cannot reconstruct from a field name.

Key design points carried from that discussion:

  • Exclusion follows affirmation (named invariant, @ajdelaguila's gating rule). A supersedes edge an automated writer proposed does not remove the incumbent; the incumbent keeps governing until an appended, attributed resolution event puts it in force. This is what lets an automated writer propose supersessions without silently displacing live guidance.
  • Append-only resolution, three readable states - never questioned / contested-and-open / contested-and-settled - distinguishable from the edges alone, no adjudication engine required.
  • Stable concept ids per Keeping OKF bundles healthy as they evolve: stable IDs, frontmatter relationships, and a rationale trail #120 for both edges and their resolution events, so a path move cannot un-affirm or misattribute a supersession.
  • Composes with the affirmation-status axis (proposed | accepted | superseded | deprecated) without either side bending.

Scope

Deliberately limited to the two lifecycle edges. Arbitrary producer-defined relationship typing (writes_to, imports_from, per #183) is a broader problem and is out of scope; the note in the proposal explains how a broader links: carrier could host these two edges without redefining them.

Reference implementation

The Lexenne remember exporter ships both keys in production. The proposal includes a sample bundle exercising all three resolution states, built from public docs.

For maintainers

The design converged across the three producers on #148 before this PR: contested_by is canonical (the more-adopted production term), contradicts is retained as a back-compat alias with Throughline migrating to match, the closing bound folds into #159's validity.valid_until, and the affirmation event's home is the bundle's log.md (section 7). The open question is now yours: whether this lands as an EXTENSIONS.md-style registry entry or a standalone proposal doc (this PR follows #159's proposal-doc pattern), and whether OKF wants to adopt the two edges as a documented convention. Happy to reshape to whichever container you prefer.

Related

#148 (home thread), #158 (maintenance-signals integration view), #159 (reliability object - the intra-concept axis these edges compose with), #120 (stable ids), #183 (arbitrary typed links - the broader out-of-scope case).

@ajdelaguila

Copy link
Copy Markdown

The write-up reads faithful to where #148 landed, and pinning the resolution event to log.md closes the location question cleanly. One convergence edit on the contested_by side, because the definition and the State 3 sample point in slightly different directions.

contested_by is defined symmetric, both sides carry the edge, and State 3 says the edge is retained regardless of disposition so a settled contest stays distinguishable from one never raised. The State 3 supersession sample keeps that on the losing record, which still carries contested_by back to the winner, but not on the winner itself, which carries only supersedes. A consumer that lands on the winner, which is the in-force survivor it will actually retrieve, then sees a supersession pointer and no contest marker at all.

supersedes alone does not recover that the winner emerged from a contest. The composition-with-status section describes a successor entering as proposed carrying supersedes with no contest in front of it, so an uncontested replacement and a contest that was fought and won produce the same shape on the surviving record. The distinction State 3 exists to preserve, settled contest versus never raised, is then lost on exactly the record most reads land on.

So the question is whether the winner should also retain contested_by back to the loser in the State 3 sample, keeping the symmetric definition intact, or whether the intent is that supersedes subsumes the contest provenance on the winner side. Either is defensible, but if it is the second then the symmetric, retained-regardless-of-disposition wording wants narrowing to say retention goes asymmetric once a supersession settles the contest, so a consumer is not told to expect a marker the winning side no longer carries.

@andrewcrenshaw

Copy link
Copy Markdown
Author

Good catch, and it's a real inconsistency in the sample rather than the definition. Going with keeping the symmetric definition intact: the winner should retain contested_by back to the loser too.

The reasoning that makes it Option A cleanly: contested_by is contest provenance, symmetric and retained on both sides regardless of disposition, and open-versus-settled is read from valid_until plus the log.md resolution event, not from the presence of the edge. So retaining it on the winner does not blur open and settled. What it does buy is exactly the distinction you flagged: a pure supersession, a clean replacement that never went through a contest, carries no contested_by on either side, so contested_by on the winning record is precisely the marker that this supersession emerged from a fought contest. Drop it from the winner and, as you say, a won contest and an uncontested replacement collapse to the same shape on the record most reads land on.

Fixing the State 3 sample so the winner carries both supersedes and contested_by, and adding a line making explicit that the two edges encode different facts and that settled-versus-open rides on valid_until plus the log.md event. Pushing the edit to the branch.

@inkxel

inkxel commented Jul 13, 2026

Copy link
Copy Markdown

Small process ask, unrelated to the substance — happy for it to be a no.

The write-up describes this as a convergence across three production implementations, and the design notes credit it that way throughout. Would you consider Co-authored-by: trailers on the commits so the git history says the same thing the doc does? As it stands the commit metadata reads as solo authorship, which undersells @ajdelaguila's gating rule in particular — exclusion-follows-affirmation is the load-bearing invariant in there and it came out of his point on #148.

One practical snag before you touch anything: cla/google is a required check and it's passing right now. Each trailer email needs a CLA on file, so adding someone who hasn't signed would flip a currently-green PR red. I've signed; I don't know where anyone else stands. So it's up to you who goes on it, or whether it's worth the hassle at all — the credit you've given in the text is already generous and I'm not fussed if that's where it stays.

@andrewcrenshaw

Copy link
Copy Markdown
Author

Absolutely, and thank you for raising it aimed at @ajdelaguila. The doc says three producers converged; the history should say the same, and exclusion-follows-affirmation being his is exactly the kind of thing that should be legible in git, not only in prose.

The CLA check is the one real gate, so let me handle it transparently instead of guessing and flipping it red. I'll add Co-authored-by: trailers for anyone whose email has a Google CLA on file. Could each of you who wants to be on it reply with the exact Name <email> to use? You've said you've signed - send the email you signed under. @ajdelaguila, same to you if you've signed and want it; your gating rule earns the line. Anyone who hasn't signed or would rather not bother, the text credit stays and stands on its own.

Once I have the confirmed line-up I'll amend the commits and re-push, then watch cla/google go back green before calling it done.

@inkxel

inkxel commented Jul 14, 2026

Copy link
Copy Markdown

Cheers, appreciate it — David Tucker <david@tucker.fm> is the one I signed under.

@ajdelaguila

ajdelaguila commented Jul 14, 2026

Copy link
Copy Markdown

Thank you both, this is really kind. I appreciate the thought and the care you have taken to recognize everyone’s contribution. It has been a pleasure being part of the discussion.

andrewcrenshaw and others added 2 commits July 14, 2026 12:21
…gleCloudPlatform#148)

Co-authored-by: David Tucker <david@tucker.fm>
Co-authored-by: Antonio J. del Águila <ajdelaguila@knaisoma.com>
…(symmetric edge, per review)

Co-authored-by: David Tucker <david@tucker.fm>
Co-authored-by: Antonio J. del Águila <ajdelaguila@knaisoma.com>
@andrewcrenshaw andrewcrenshaw force-pushed the okf-typed-relationship-edges branch from 51256cf to a3dcb73 Compare July 14, 2026 16:26
@andrewcrenshaw

Copy link
Copy Markdown
Author

Antonio — thank you again, and one small snag to sort. The Google CLA bot
isn't matching your @knaisoma.com to a signed CLA, so it's flagging
that address on PR #195. Two usual causes: the CLA is on file under a
different email, or your @knaisoma.com address isn't verified/attached on
your GitHub account (Settings → Emails), which the bot also checks.

If you confirm that email is on your GitHub account and matches your CLA
record, then hit the "rescan" link on the PR's CLA check, it should flip
green with your co-author line intact. If it's easier to use a different
email that's already on your CLA, tell me which and I'll swap the trailer.

@ajdelaguila

Copy link
Copy Markdown

That's interesting @andrewcrenshaw, I actually have it verified and set as my primary email address:
image

Any ideas what to look for?

@andrewcrenshaw

Copy link
Copy Markdown
Author

Thanks Antonio — the GitHub verification is one half; the CLA record itself
is the other. A rescan already ran on my side and it's still not matching
ajdelaguila@knaisoma.com, which usually means the CLA is filed under a
different email than that one (Google ties the CLA to the Google account you
signed in with).

Could you open https://cla.developers.google.com/clas and tell me the exact
email your CLA is listed under? Two ways it resolves:

  • If it's a different email that's also on your GitHub account, just send it
    and I'll set the co-author line to that address — no re-signing needed.
  • If it already says ajdelaguila@knaisoma.com, then it's the GitHub-username
    link on the CLA record that's missing; that same page lets you check it,
    and the next rescan should pass.

Whichever's easier — I just need the exact email your CLA shows.

@ajdelaguila

Copy link
Copy Markdown

My bad @andrewcrenshaw, I didn't have a CLA record created. Now it's created, matching the email and username in my GitHub account.

@andrewcrenshaw

Copy link
Copy Markdown
Author

All green now @ajdelaguila. Thanks!

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.

3 participants