Repository navigation
Proposal: register query-time semantics for supersedes and contested_by on the #16 carrier #22
Description
#16 gives relationships a carrier: to, type, direction, and the §5.3 trust shapes one level down. It deliberately leaves type producer-defined and unconstrained, and that is the right call for the carrier. This proposes the other half for two specific types, because a consumer reading type: supersedes still cannot tell whether to drop the target from an in-force query.
Two lifecycle edges, each with its query-time semantics registered beside it. They differ on the axis that drives consumer behaviour: directionality.
Revised 2026-09-14 from review by @ajdelaguila and @3a3; the comment thread carries the derivation.
The two types
supersedes |
contradicts |
|
|---|---|---|
| Symmetry | Asymmetric. The carrying concept replaces the referenced one. | Semantically symmetric, stored one-sided. Written on the asserting concept only; the reverse is derived. |
| Direction | Backward in time, to the concept being replaced. | Outbound from the asserting concept. direction reads as it does for any asymmetric type. |
| Query-time | Exclude, once affirmed. Drop the superseded concept from in-force retrieval; retain it in the bundle for lineage. | Surface both. Never resolve the edge as a verdict, collapse "contested" into "false", or drop a side without human or higher-signal input. |
| Encodes a verdict? | Once affirmed, yes. | No. Records that a dispute exists, never who is right. |
| Inverse emitted? | No. Resolution keys on the forward edge only. An inverse spelling gives a producer two ways to state one relationship and a consumer two places to look, which is how a reversed edge survives review (@jpavley shipped one inverted, GoogleCloudPlatform/knowledge-catalog#148). |
Derived, never written. See the naming section. |
| Dangling target | Not an error. If the target is absent, the carrying concept is current. | Not an error. |
relationships:
- to: remember://lesson/lesson-corpus-est-000
type: supersedes
generated: { by: remember/0.2, at: 2026-09-12T09:00:00Z }Targets are stable concept ids per GoogleCloudPlatform/knowledge-catalog#120, not paths, so a file move cannot reattach an edge to the wrong incumbent. @pixie79 reports the same conclusion from the other end on #16: deriving a concept's path from its key guessed wrong for 43 links on a real render, each a valid-looking path to a file that did not exist.
Naming: one stored key, one derived view
contradictsis the stored key, on the asserting concept, one side only.contradicted_byis the derived reverse view, computed at read time and never written to frontmatter.contested_byis a deprecated spelling. Consumers SHOULD read it ascontradicts.
Under one-sided storage contested_by is inverted: the asserter would carry a key saying it is contested, the reverse of what it asserts. This registration, @inkxel's implementation and Data Olympus's are then one vocabulary rather than three. We ship contested_by today and have the migration to do.
A mirror write, with both records carrying the edge, is a two-write that can half-apply, and a one-sided contest is a different condition from the dangling target ruled benign above. Derivation costs a consumer nothing that it is not already paying: a reverse index over stable ids is what resolves targets at all.
Three rungs, and only the third authorizes exclusion
With verified and generated available on the edge it is tempting to read edge provenance as authorization. It is not, and neither is the middle rung.
- Edge provenance -
generated/verifiedon the relationship. Says who asserted the edge. Authorizes nothing. @pixie79 confirms the carrier claims no more: "our edges carrykind,provenanceandconfidence, and none of that is an affirmation." - Source eligibility - the asserting concept is itself in force. Data Olympus ships this: an in-force query excludes the target of a
supersedesedge whose source is in force, an edge asserted from an inbox document excludes nothing whatever status it claims, and a dangling edge excludes nothing because the join needs both ends to resolve. - Attributed resolution - someone affirmed this retirement, recorded as an appended, attributed event.
Exclusion follows affirmation. An automated writer may propose a supersession; the incumbent keeps governing until the resolution event is recorded. Rung 2 is weaker than rung 3 and is named rather than collapsed into it, because it is what a real implementation runs today: source eligibility says the edge comes from something currently governing, it does not say anyone affirmed this particular retirement. That distinction is what a consumer needs when 18,803 of 19,349 edges are derived.
Exclusion requires both. A present forward edge and a readable affirmation, together. An affirmation surviving in log.md after the edge is removed from the successor, or after the successor leaves the bundle, is incomplete evidence, so the incumbent stays in force.
The resolution event
Where it lives: the bundle-root log.md. Nearest-ancestor would make the in-force answer depend on where a concept sits in the tree, so a file move could change which log governs its retirement, contradicting the stable-id rule above. A resolution entry in a non-root log.md is not an affirmation; §9 permits the file at any level, and an entry elsewhere excludes nothing.
§9 supplies the file's shape and no preservation duty (SPEC.md:535-552), so the append-only behaviour this registration depends on is the producer's to supply, not the format's. For a bundle assembled in parts that producer is the merging one: it writes root reserved files after merging and carries forward every log.md entry it did not write, from the existing file or from its own bookkeeping. @3a3's #26 §3.2 now states this (revised 2026-09-14); their merge becomes read-then-add, keeping each such entry unchanged under its original date heading.
Entry shape, in §9's own idiom - its **Update** / **Creation** / **Deprecation** convention, made normative inside this registration rather than in core:
## 2026-09-14
* **Supersession**: `remember://lesson/b` supersedes `remember://lesson/a`. Affirmed by `human:1c8998e4`.
* **Dismissal**: contest between `remember://lesson/c` and `remember://lesson/d` dismissed. Affirmed by `human:1c8998e4`.A consumer MUST find four things: the disposition word, both stable concept ids, and the attributing actor in §7's form. The date comes from the enclosing §9 heading.
Absent, malformed or undecidable evidence fails safe. If any of the four is missing or unparseable, the entry is not a readable affirmation, so the incumbent stays in force and nothing is excluded. The same answer covers conflicting entries: §9 orders dates newest first and says nothing about order inside a date, so two conflicting entries on one pair under one heading are not decisive. This also answers a real adoption case - @pixie79 reports on #16 that Roteiro populates no author fields and discards a peer's author on import. That producer excludes nothing rather than excluding wrongly, and needs no change to stay conformant.
Where the conformance layer lands: in this registration, not §11. Core should not carry a clause for a community extension it does not define. A consumer implementing this registration gets a checkable bar; a bundle that ignores the registration is unaffected.
Three states, read from the bundle alone
No adjudication engine, no edited records, every resolution an append.
- Never questioned - no
contradictspointing at it, not the target of anysupersedes. Absence means no dispute asserted, not proven undisputed. - Contested and open - the edge exists, both concepts present, no resolution recorded. Surface both.
- Contested and settled - a resolution is recorded, not edited in. The
contradictsedge is retained whatever the disposition, so a settled contest stays distinguishable from one never raised. Drop it and a reader returning later cannot tell a question that was settled from one that was never asked.
A supersedes edge with no resolution event yet is a proposal, not a fourth state: both concepts surface and the incumbent stays in force.
Settlement comes two ways.
Supersession - the winner gains the supersedes edge, the loser's validity window closes, both retain contradicts, and exclusion keys on the resolution entry rather than on the closed window. A closed window with no entry is decay, and reading it as affirmation would collapse decay and affirmed supersession into one, which is the silent displacement the invariant forbids.
Dismissal withdraws the contest, not a concept. No window closes, both concepts stay in force, and the entry's whole job is moving the pair from contested-and-open to contested-and-settled. A concept examined and judged wrong is #13's refuted or a supersession; dismissal is not a third way to retire something, and contradicts carries no verdict by design.
Composition
- §5.4
statussays whether a concept is current; the edge says where current lives. Neither implies the other, and a consumer that understands only one still behaves correctly. §5.4 definesdeprecatedas kept for links and history, but nothing in frontmatter points from a deprecated concept to its replacement, so a consumer filtering out deprecated concepts drops the only breadcrumb at the moment it acts on the signal. - §5.3 trust tiers derive from
verified, and §10.6 makes verification doc-level and recorded in the bundle, so a concept human-reviewed in June can be contested in July with its tier intact. A tier-filtering consumer surfaces it as human-reviewed and never sees the dispute unless the contest is typed. - Proposal: Third trust field
refuted#13 (refuted) is a trust event on a concept that exists; these are relations between concepts.contradictsdefers adjudication by design and carries no verdict, so it does not overlap. - Proposal:
imported— attribute a concept taken from another bundle without inheriting its trust #15 (imported) composes: an imported relationship reports the upstream's tier without inheriting it. - Deletion semantics: a removed concept and a concept that was never written are indistinguishable to a consumer enumerating a bundle #11 (deletion semantics) is the presence axis. A superseded concept stays in the bundle; a removed one needs an absence record.
- Proposal: producing a bundle in parts — reserved filenames collide on merge, and a regenerated bundle-root
index.mdmay dropokf_version#26 (bundles in parts) carries the merge-side obligation this registration depends on.
Floor for partial implementation. A consumer that implements the carrier and not this registration excludes nothing. Under exclusion follows affirmation that is the designed failure direction, not an accident.
Provenance
Two production implementations, arrived at independently. Ours ships both keys in the remember exporter with the sample bundle at https://github.com/andrewcrenshaw/remember-okf-sample-bundle. @ajdelaguila's Data Olympus ships source-gated supersession over concept ids and holds contradicts as annotation that never filters, with contest disposition open at knaisoma/data-olympus#241. The two differ on one mechanism: Data Olympus reads a contest-to-supersession count out of git diffs, and we record a resolution event at settlement so the same count is a query. That difference is the argument for rung 3.
The prior text, with the extended composition and a worked sample bundle, was GoogleCloudPlatform/knowledge-catalog#195, now retired in favour of this. Its own adjacent-proposals section predicted this carrier: a broader carrier for producer-defined relations can host these two edges without redefining them, because the query-time semantics attach to the relation and not to the syntax.
Glad to take further convergence edits here and then put it up as a PR.
Activity
ajdelaguila commentedon Sep 12, 2026
Reviewed. A few things to settle in the text, most of them about rung 3.
Where the resolution event lives is underspecified for a consumer that has to act on it. §9 fixes the file's shape, a flat list of date-grouped entries newest first under ISO date headings, and then says entries are prose, with the leading bold word a convention rather than a requirement. Nothing in the spec names the fields an affirmation must carry, so two consumers reading the same entry can disagree about whether this particular retirement was affirmed, which is the one question the invariant makes decisive. The fix need not be a separate carrier: register the entry shape inside
log.md, name what a consumer must find (both stable ids, the attributing actor, the date), and say what a consumer does when that evidence is absent or malformed. Whether that lands as a conformance layer belonging to the registration or as a companion clause in §11 is your call, but the text should say which, because today a bundle whose resolution entries are unreadable is still conformant with base OKF.Related and smaller: §9 allows a
log.mdat any level of the hierarchy, and the text says "the bundle'slog.md" in the singular. Nearest ancestor of the carrying concept and bundle root are both defensible, but left unstated, two conformant consumers can reach different in-force answers from the same bytes.On
contested_bybeing symmetric. Requiring both sides to carry the edge is a two-write that can be half-applied, and a one-sided contest is a different condition from the dangling target you already rule benign. Here only the one-sided form is stored,contradictson the asserting document, with the reverse computed at read time and surfaced ascontradicted_by, dangling-safe at both ends. If the registration says one side is sufficient and the inverse is derived, symmetry holds without a write that can half-fail, and thecontradictsalias lines up mechanically rather than only sounding similar. The carrier'sdirectionthen wants a line saying how to read it on a symmetric type, or that consumers ignore it there.Last, worth stating rather than leaving to inference: a consumer that implements the carrier and not the resolution excludes nothing, which under exclusion follows affirmation is the safe direction to fail in. Naming "surface both" as the floor makes that read as designed.
andrewcrenshaw commentedon Sep 14, 2026
All four accepted, one of them changing a position the text called load-bearing. Revised registration below; the original body stays as filed so the review reads in order.
1. The resolution entry now has a shape
You are right that rung 3 was unenforceable. §9 fixes the file and leaves the entry as prose, so "an appended, attributed resolution event" named a location and not a contract.
Registered entry shape, in §9's own idiom (its
**Update**/**Creation**/**Deprecation**convention, made normative inside this registration rather than in core):A consumer MUST find four things: the disposition word, both stable concept ids, and the attributing actor in §7's form. The date comes from the enclosing §9 heading.
Absent or malformed evidence fails safe. If any of the four is missing or unparseable, the entry is not a readable affirmation, so the incumbent stays in force and nothing is excluded. That is the same direction as your point 4 and it answers a real adoption case: @pixie79 reports on #16 that Roteiro populates no author fields and discards a peer's
authoron import. Under this rule that producer excludes nothing rather than excluding wrongly, and needs no change to stay conformant.Where it lands: in this registration, as a conformance layer, not in §11. Core should not have to carry a clause for a community extension that core does not define. Naming it here means a consumer implementing this registration has a checkable bar, and a bundle that ignores the registration is unaffected.
2. One
log.md, at the bundle rootThe bundle-root
log.md. Nearest-ancestor makes the in-force answer depend on where a concept happens to sit in the tree, so moving a file could change which log governs its retirement, which contradicts the stable-id rule the rest of this registration rests on.The root also matches how a merged bundle is actually built: @3a3 on #26 keeps reserved filenames out of directories more than one part contributes to and has the merging producer write the root
index.mdandlog.mdafterwards. Root is the one place a bundle assembled in parts has a single authority.3.
contested_bybecomes one-sided and derived, and this changes our positionAccepted, and it retires a load-bearing invariant in the filed text.
Store the edge once, on the asserting concept. The reverse is computed at read time and surfaced as the inverse view; it is never written. Dangling-safe at both ends, and no write that can half-apply.
What that costs and why we think it is worth paying: the filed text required both records to carry the edge so either reads standalone without a second lookup, a storage-versus-identity split @jpavley contributed on
GoogleCloudPlatform/knowledge-catalog#148, with a validator completeness check because a mirror can half-fail. The decider is that a consumer is already building the reverse index. @pixie79 reports on #16 resolving every link through akey -> pathmap built after placement, after path-from-key guessed wrong for 43 links on a real render. Where that index exists, derivation is nearly free, and jpavley's completeness check stops being an unenforced obligation because there is no longer a second write to lose.It also settles the naming honestly.
contradictson the asserting concept with a derived inverse is the same mechanism, not a spelling to alias.On
directionfor a symmetric type: with one-sided storage the question dissolves.directionreads exactly as it does for an asymmetric type, outbound from the asserting concept. The symmetry lives in the query-time semantics, where both sides surface, not in the storage.4. Surface-both is the floor, stated
A consumer that implements the carrier and not this registration excludes nothing. Under exclusion follows affirmation that is the designed failure direction, not an accident of partial implementation, and the text now says so.
Glad to fold this into the issue body once it has settled, or to leave body and revision separate if that reviews better.
ajdelaguila commentedon Sep 14, 2026
Leaving the body as filed and folding once it settles works well from here, as long as the fold lands before the PR so a maintainer reviews one document. The root
log.mdand the conformance-layer placement both read right. One line saying a resolution entry in a non-rootlog.mdis not an affirmation would close the case §9 still permits.Three smaller things.
The dismissal entry does not say which side lost. The filed text has a dismissal close "the dismissed side's window", but
contest between c and d dismissednames the pair without a direction, so a consumer cannot tell which window the receipt accounts for. Either the entry names the dismissed id, or dismissal means the contest itself was dismissed and closes no window. Both work, and the text should pick one.The log and the frontmatter can disagree, and the fail-safe rule could cover that as well as malformed entries. An affirmed supersession stays in
log.mdafter someone removes thesupersedesedge fromb, or afterbleaves the bundle. Saying exclusion needs both a present forward edge and a readable affirmation keeps the incumbent in force when that evidence is incomplete. The same applies to two conflicting entries on one pair under a single date heading, since §9 orders dates newest first but says nothing about order inside a date.On naming, the table still registers
contested_byas canonical withcontradictsas an alias, while the revision now sayscontradictsis the same mechanism rather than a spelling to alias. A consumer building the reverse index needs to know which key is stored and whether the derived view has a name of its own. Data Olympus storescontradictsand serves the computed reverse ascontradicted_by, never written to frontmatter, which is one answer. The registration only needs to state its own.andrewcrenshaw commentedon Sep 14, 2026
All four, and the last one changes a key we ship.
Folding before any PR, agreed. One document for a maintainer is the right bar and the body will carry the settled text.
Non-root logs. Added: a resolution entry in a non-root
log.mdis not an affirmation. §9 permits the file at any level and a consumer may find a resolution-shaped entry there; only the bundle-root log carries affirmations, and an entry elsewhere excludes nothing.Dismissal closes no window
The filed text closes "the dismissed side's window" while the registered entry names a pair without a direction. Taking your second option: dismissal withdraws the contest, not a concept. No window closes, both concepts stay in force, and the entry's whole job is to move the pair from contested-and-open to contested-and-settled so a settled question stays distinguishable from one never raised.
That composes better than the alternative. A concept examined and judged wrong is #13's
refutedor a supersession; dismissal should not be a third way to retire something, and the registration already holds thatcontested_bycarries no verdict by design. The entry needs no direction under that reading.Exclusion requires both, and undecidable evidence fails safe
Accepted, and it generalises the rule rather than adding a case. Exclusion requires a present forward edge and a readable affirmation, together. An affirmation surviving in
log.mdafter the edge is removed fromb, or afterbleaves the bundle, is incomplete evidence, so the incumbent stays in force.Your conflicting-entries case lands in the same rule. §9 orders dates newest first and says nothing about order inside a date, so two conflicting entries on one pair under one heading are not decisive, and the incumbent stays. Undecidable and unreadable get the same answer, which is the point of fail-safe.
The stored key is
contradictsUnder one-sided storage on the asserting concept,
contested_byis inverted: the asserter would carry a key saying it is contested, the reverse of what it asserts.contradictsreads correctly in that position andcontradicted_byis its natural derived view. The name follows the storage model, andcontested_bywas shaped for the mirror-write this registration no longer specifies.Registered, replacing the alias row in the body:
contradictsis the stored key, on the asserting concept, one side only.contradicted_byis the derived reverse view, computed at read time and never written to frontmatter.contested_byis a deprecated spelling. Consumers SHOULD read it ascontradicts.That makes @inkxel's, Data Olympus's and this registration's spellings one vocabulary rather than three. We ship
contested_bytoday and have the migration to do, which is the right way round given two of three producers already storecontradicts.3a3 commentedon Sep 14, 2026
Your revision's §2 holds for the producer it cites: every part contributes to the bundle root and no part owns it, so no part writes the root
log.md; the merging producer does, after merging (#26, §3.2, third bullet).§2 describes that bullet as filed; it was revised on #26 after your comment there and is now in the #26 body. The half §2 leaves out is the one an affirmation depends on: §9 fixes the file's shape and gives it no preservation duty (
SPEC.md:535-552), so the "append-only" the body relies on is the merging producer's to supply. In short, for the fold-in you offered: the merging producer writes root reserved files after merging and carries forward everylog.mdentry it did not write, from the existing file or its own bookkeeping. Ours, as said on #26, becomes read-then-add and keeps each such entry unchanged under its original date heading.mlnrt commentedon Sep 23, 2026
Just wanted to share how I am planning to handle
supersedesin our Arkeology plugin (which uses external storage, AWS S3 Bucket and Vectors, to store artifacts instead of git) and how I plan to map onto the three rungs.We agree with "exclusion follows affirmation", and we reach rung 3 without a
log.md.We have no bundle root, so a resolution entry there is not available to us. Instead we key the in-force decision on the artifact's own retired concept's
status: deprecated(§5.4), attributed through that concept's ownrevised.by.Our in-force filter is one clause on the concept being evaluated:
archivedis our store's own marker (set by an explicit archive operation, orthogonal to §5.4). Thesupersedesedge does not appear in the clause at all. Taking B —supersedes→ A:stable.stable, not archived). A stillstable.status: deprecated— with or without any edge pointing at it.status, whatever edges point at it.Why the flip on A counts as affirmation rather than provenance: the B→A edge is cheap, often machine-derived, and written on a different document than the one it retires — which is exactly why the thread doesn't trust it alone.
status: deprecatedon A has none of those properties. It is a write to A, so it sits under whatever already governs writes to A. Deprecation is no escalation of power over what any writer to A already holds (they could archive or delete it), and it is attributed. Cross-scope falls out for free: another team's B may declare it supersedes our A; it cannot write our A, so A stays in force in our results and their claim is visible as lineage (In Arkeology we can share artifacts cross projects/teams).Two consequences that line up with the registration as revised: a dangling
supersedestarget is benign (the carrying concept is current), and the edge-without-deprecation state is precisely "proposed, not affirmed" — visible, not acted on.One ask. The registration currently names bundle-root
log.mdas the home of the attributed resolution and says an entry elsewhere excludes nothing. Would you consider naming "the target itself carriesstatus: deprecated, attributed" as a second acceptable form of attributed resolution? It gives store-backed consumers a conformant path, and for bundle consumers it is already what §5.4 means.The dependency is that producers write both ends — the edge on the successor and the status flip on the incumbent. Ours does; I'd be interested whether Roteiro's and Data Olympus's do, since if the edge is ever written alone the incumbent stays in force under
this rule, by design.
ajdelaguila commentedon Sep 23, 2026
Ours retires the incumbent from the successor's edge alone, which puts us at your rung 2.
in_force=trueexcludes any document that is the target of asupersedesedge whose source is itself in force under the full predicate, meaning status class, validity window, and not a memory-inbox record. A draft, an expired document, one already retired, or an inbox record cannot retire anything by naming it insupersedes. The documentation calls this closing the forgotten status flip gap: A supersedes B, B's own status was never updated, and B still leaves in-force results.On your literal question, the two ends are separate writes here.
kb_propose_editnames a singletarget_path, held under a per-path lock, with a compare-and-swap when the caller supplies a base marker, so the edge on the successor and a status flip on the incumbent are two edits rather than one change. A newly introducedsupersedesvalue is checked against a document present in the commit being made. Retrieval exclusion does not depend on a separate status flip on the incumbent, which is the property that matters for your rule.The guard on the source and your target-side write are different checks. We test the successor's status, validity window and inbox placement; you tie retirement to the permissions governing the incumbent. Yours gets cross-scope safety out of that, since another team's B cannot write your A, and where a store shares artifacts across teams that is a real advantage of keying the decision on the target.
Your dangling-edge consequence holds here too, for a mechanical reason: the exclusion query joins edges to documents at both ends. The other one differs, since a qualifying edge is acted on rather than left visible and unacted. What we keep instead is explainability. A plain search still returns the excluded document, and
kb_getreportssuperseded_byas the union of the document's own claim and any reverse edge, so a consumer can see what retired it.https://github.com/knaisoma/data-olympus/blob/v0.9.0/docs/serving.md#supersession-graph-exclusion-issue-110-slice-2
Your ask reads right to me. If the registration names an attributed
status: deprecatedon the target as a second form of resolution, it is worth saying in the same clause that an edge alone affirms nothing under any named form. Our rule excludes the incumbent before that requirement is met, and naming the floor is what lets a producer writing one end predict the consumers that do not.bundle: regenerate with PCC-7034 contradicts — the exporter writes th…
bundle: regenerate with PCC-7096 — a confirmed supersession is record…
DavidROliverBA commentedon Sep 27, 2026
Thanks for this thread; it is the most careful discussion of
supersedesandcontradictsI have seen anywhere, and I wanted to add a second implementation's data point in case it helps the convergence along.I maintain AI-XF (https://github.com/DavidROliverBA/ai-xf-format, MIT), a small superset of OKF v0.2 that I use to move knowledge between my own vaults and agents. It has carried typed links, with
contradictsandsupersedesas core relationship values, since its first draft in July, and I was glad to see this thread settle on the same spelling after droppingcontested_by.One honest difference, offered as a comparison rather than a counter-proposal. Here, resolution is an attributed event in the bundle-root
log.md, exclusion follows affirmation, and malformed evidence fails safe. In AI-XF, resolution is state on the edge itself:state: open | resolvedplus aresolved: {by, at, outcome}map. The edge form is a single write with no shared file to fight over; the log form keeps a history and is auditable. I suspect they compose, edge for current state and log for history, and I would happily align AI-XF with whatever this thread lands on.What might be useful: before writing the federation rules into AI-XF v0.4, I tested each one. The repo has three deliberately colliding fixture bundles and six re-runnable experiments, plus a run on two real bundles from my vault. The collision experiment found that an unqualified reference across a bundle boundary should never resolve silently (0 silent misresolutions with a warn-and-name rule), and the transport experiment found that a consumer manifest is needed for provenance rather than resolution, which surprised me. The fixtures and results are yours to reuse if they help test a reader against these semantics.
To be clear about intent: I would much rather OKF win as the standard than have a superset persist. AI-XF exists to try things ahead of the spec, and every feature OKF adopts gets retired from AI-XF in favour of the OKF definition, as happened with the trust fields in v0.2. If this thread's resolution semantics land in OKF, I will do the same here.
andrewcrenshaw commentedon Oct 3, 2026
Taking @mlnrt's second form, with @ajdelaguila's clause in the same sentence: an edge alone affirms nothing under any named form. Store-backed consumers have no bundle root, so without it rung 3 is out of their reach by construction, and §5.4 already defines
deprecatedas "no longer current". A write to the incumbent also sits under whatever governs writes to it, which is where the cross-scope safety comes from.Two conditions, measured against the four elements a resolution entry carries. The edge stays required: the flip on A supplies the disposition and the pair comes from B's
supersedesedge, so a deprecated A with nothing pointing at it is §5.4's business and #22 neither claims nor contradicts it. Attribution needs a source core does not have yet: nothing in the spec attributes a status change andrevised.byis #28, so the form is named as attributed and the existing fail-safe applies until a source is readable. The cost is in audit rather than exclusion. A log entry records that B replaced A, the flip records only that A was retired.@DavidROliverBA's edge form makes the axis visible: which document the affirmation is written on. The log entry sits in a bundle-root file the producer governs, the flip sits on the incumbent, and
resolved: {by, at, outcome}sits on the asserting document. Inside one producer's bundle the three come out equivalent. Across bundles they do not, because edge state lets one bundle retire another bundle's concept with a single write on its own side. Your collision result reaches the same place for identity; applied to authority, a cross-bundle supersession should not affirm itself. So edge state serves well as the current-state view and spares the shared-file contention you name, the same cost behind #26's merge-preservation rule, while deferring across bundles to an affirmation the asserter does not control.On whether producers write both ends: ours writes the edge on the survivor and a resolution entry in bundle-root
log.md, and nothing on the incumbent. The entry's wording still differs from the registered example, which is ours to bring in line.Glad to fold the second form, the clause and the cross-bundle sentence into the body once the wording settles here.