1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! Cross-repo external references (ADR-0009, the persisted `inferred` links).
//!
//! An inferred cross-repo link connects a config key in one repo (the *spoke*)
//! to its counterpart in another (the *hub*). The two endpoints live in
//! **different** graph stores, but the store's integrity rule requires both ends
//! of an edge to resolve to a node in the *same* store. So the spoke store gets
//! an **external-ref node** — a local placeholder standing in for the hub's node,
//! carrying the project-qualified target key — and the inferred edge points at
//! that placeholder. Store integrity holds locally, while the [`crate::Workspace`]
//! resolver still follows the placeholder across repos to the real node (see
//! [`crate::Workspace::follow_external_ref`]).
//!
//! These facts are not derivable from the spoke's own blobs (they need the hub),
//! so they are persisted as an **import layer** under [`LINKS_REF`] and re-applied
//! after every sync — dangling edges pruned when a config key is removed — reusing
//! the same durability machinery lat.md and Graphify imports rely on.
use crateProvenance;
use crate;
/// The import-layer `src_ref` under which inferred cross-repo links are persisted
/// (see [`crate::Store::apply_import_layer`]). Its own producer, so re-inferring
/// can re-derive it authoritatively without touching other import layers.
pub const LINKS_REF: &str = "import:links";
/// The import-layer `src_ref` for **authored** cross-repo links — a repo's
/// `[[links]]` declarations (ADR-0009), as opposed to [`LINKS_REF`]'s inferred
/// matches.
///
/// A **separate** ref, and that is the load-bearing part. `apply_import_layer`
/// is authoritative per ref: it clears the ref's prior edges before re-applying.
/// Sharing one ref would therefore make `links --write` delete every inferred
/// edge and `links --infer --write` delete every authored one — each command
/// silently reclassifying the other's work on every run.
///
/// It is also what lets "authored → gold, inferred → slate" mean anything: the
/// two provenances have to be independently replaceable, or re-running one
/// changes the colour of the other.
pub const LINKS_AUTHORED_REF: &str = "import:links/authored";
/// The node-kind token for an external-ref placeholder — a stand-in, in one
/// repo's store, for a node that actually lives in another repo's graph.
pub const EXTERNAL_REF_KIND: &str = "external_ref";
/// Build an external-ref placeholder node for a **project-qualified** target key
/// (`<project>::<key>`, ADR-0009). The node lives in the *referring* repo's store
/// so an inferred edge to the (foreign) target satisfies store integrity; its
/// qualified target is recorded in `meta` so [`crate::Workspace::follow_external_ref`]
/// can resolve it across the workspace. Tagged [`Provenance::Inferred`].
/// [`external_ref_node`], with the placeholder's provenance chosen by the caller.
///
/// The placeholder carries the provenance of the *claim that the target exists*:
/// [`Provenance::Inferred`] for a confidence-scored match, [`Provenance::Authored`]
/// for a `[[links]]` declaration someone wrote.
///
/// # The placeholder's provenance is not the link's
///
/// Both flavours share a key, so a repo that both declares *and* infers the same
/// target has **one** placeholder — and since each layer upserts it, the node's
/// own provenance is whichever layer was applied last. Do not read it as the
/// link's provenance. The **edges** carry that, one per ref, and a consumer
/// asking "is this link authored?" must look there:
///
/// ```text
/// "incoming": [
/// { "provenance": "authored", "confidence": null },
/// { "provenance": "inferred", "confidence": 0.9 }
/// ]
/// ```
/// The store key of the external-ref node for `qualified` — the qualified target
/// under an `extref:` namespace, so it never collides with a real node key.
/// The project-qualified target of an external-ref `node`, or `None` if `node` is
/// not one. Read from `meta.qualified`, falling back to the `extref:` key prefix
/// so a node written by an older layer still resolves.