link
Records that key's run produced each of propositionIds, in that run's tenant.
Idempotent: the link is merged on the pair, so re-running an extraction that produced the same claims writes nothing new and returns the same number. That is what makes the relation safe to write from a path that can be retried.
An empty batch is a no-op and touches nothing.
Return
How many links now join this run to these propositions. Equal on a replay.
Parameters
The run, tenant-qualified.
Canonical ids of the propositions the run produced. Duplicates in the collection are one link.
Throws
if this tenant has no run under that id. A claim attributed to a run nobody recorded is a dangling audit row.
if any id names a proposition this tenant does not hold, whether it does not exist at all or belongs to a neighbour. Nothing is written.
The failures listed above must not damage the caller. Lineage is written best-effort by a caller that catches and carries on, so raising one of them has to leave everything else exactly as it was — including a transaction the caller is running in. They are all raised after the implementation's own reads and writes have succeeded, which is what makes that possible; an implementation that joins a caller's transaction must not condemn it on the way out. DrivinePropositionRunLinkStore's integration tests hold the one backend that has a transaction to condemn to this. The in-memory reference has none, so the shared contract suite has nothing to assert here and does not pretend to.
A failure below an implementation — a database that terminates the transaction itself — is outside this and outside any catch. See DrivinePropositionRunLinkStore.link.
link for a single proposition.