@antongolub/lockfile 0.0.0-snapshot.44 → 0.0.0-snapshot.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/SCHEMAS.md +1 -0
  2. package/dist/{_npm-flat-types-DwOV4BpV.d.ts → _npm-flat-types-C3oOIC0o.d.ts} +1 -1
  3. package/dist/{_pnpm-flat-core-_4KM9kQj.d.ts → _pnpm-flat-core-C5VUToQP.d.ts} +1 -1
  4. package/dist/{_yarn-berry-core-EKBJ_ohM.d.ts → _yarn-berry-core-sjtp6At6.d.ts} +1 -1
  5. package/dist/complete.d.ts +68 -0
  6. package/dist/complete.js +298 -0
  7. package/dist/formats/bun-text.d.ts +1 -1
  8. package/dist/formats/bun-text.js +54 -12
  9. package/dist/formats/npm-1.d.ts +1 -1
  10. package/dist/formats/npm-1.js +54 -12
  11. package/dist/formats/npm-2.d.ts +2 -2
  12. package/dist/formats/npm-2.js +78 -17
  13. package/dist/formats/npm-3.d.ts +2 -2
  14. package/dist/formats/npm-3.js +78 -17
  15. package/dist/formats/pnpm-v5.d.ts +1 -1
  16. package/dist/formats/pnpm-v5.js +96 -16
  17. package/dist/formats/pnpm-v6.d.ts +2 -2
  18. package/dist/formats/pnpm-v6.js +91 -16
  19. package/dist/formats/pnpm-v9.d.ts +2 -2
  20. package/dist/formats/pnpm-v9.js +91 -16
  21. package/dist/formats/yarn-berry-v10.d.ts +24 -0
  22. package/dist/formats/yarn-berry-v10.js +2380 -0
  23. package/dist/formats/yarn-berry-v4.d.ts +2 -2
  24. package/dist/formats/yarn-berry-v4.js +159 -27
  25. package/dist/formats/yarn-berry-v5.d.ts +2 -2
  26. package/dist/formats/yarn-berry-v5.js +159 -27
  27. package/dist/formats/yarn-berry-v6.d.ts +2 -2
  28. package/dist/formats/yarn-berry-v6.js +159 -27
  29. package/dist/formats/yarn-berry-v7.d.ts +2 -2
  30. package/dist/formats/yarn-berry-v7.js +159 -27
  31. package/dist/formats/yarn-berry-v8.d.ts +2 -2
  32. package/dist/formats/yarn-berry-v8.js +159 -27
  33. package/dist/formats/yarn-berry-v9.d.ts +2 -2
  34. package/dist/formats/yarn-berry-v9.js +159 -27
  35. package/dist/formats/yarn-classic.d.ts +1 -1
  36. package/dist/formats/yarn-classic.js +84 -13
  37. package/dist/{graph-BzsItuAI.d.ts → graph-XpDkFSjz.d.ts} +3 -1
  38. package/dist/index.d.ts +6 -2
  39. package/dist/index.js +1973 -156
  40. package/dist/modify-C4BdPHYO.d.ts +218 -0
  41. package/dist/modify.d.ts +20 -0
  42. package/dist/modify.js +988 -0
  43. package/dist/optimize-Du6S8Ld1.d.ts +33 -0
  44. package/dist/optimize.d.ts +24 -0
  45. package/dist/optimize.js +132 -0
  46. package/dist/registry.d.ts +60 -0
  47. package/dist/registry.js +649 -0
  48. package/dist/types-Ci06KZkZ.d.ts +46 -0
  49. package/package.json +22 -1
package/SCHEMAS.md CHANGED
@@ -33,6 +33,7 @@ berry's `__metadata`.
33
33
  | `yarn-berry-v6` | `__metadata.version: 6` | yarn `>=3.2 <4` | yarn `>=3.2` |
34
34
  | `yarn-berry-v8` | `__metadata.version: 8` | yarn `>=4.0 <4.14` | yarn `>=4` |
35
35
  | `yarn-berry-v9` | `__metadata.version: 9` | yarn `>=4.14` | yarn `>=4.14` |
36
+ | `yarn-berry-v10` | `__metadata.version: 10` | yarn 5 (dev branch) | yarn 5+ (preview — reverse-engineered from yarnpkg/berry master) |
36
37
 
37
38
  **Schema numbers that don't exist:**
38
39
  - `__metadata.version: 1` and `2` were never used by berry.
@@ -1,4 +1,4 @@
1
- import { D as Diagnostic } from './graph-BzsItuAI.js';
1
+ import { D as Diagnostic } from './graph-XpDkFSjz.js';
2
2
 
3
3
  interface NpmFamilyParseOptions {
4
4
  }
@@ -1,4 +1,4 @@
1
- import { D as Diagnostic } from './graph-BzsItuAI.js';
1
+ import { D as Diagnostic } from './graph-XpDkFSjz.js';
2
2
 
3
3
  interface PnpmFamilyParseOptions {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { D as Diagnostic } from './graph-BzsItuAI.js';
1
+ import { D as Diagnostic } from './graph-XpDkFSjz.js';
2
2
 
3
3
  interface YarnBerryFamilyParseOptions {
4
4
  workspaceRoot?: string;
@@ -0,0 +1,68 @@
1
+ import { N as NodeId, D as Diagnostic, G as Graph, E as EdgeTriple, a as Node, b as EdgeKind } from './graph-XpDkFSjz.js';
2
+ import { R as RegistryAdapter } from './types-Ci06KZkZ.js';
3
+
4
+ interface CompletionSeed {
5
+ /** NodeIds the modifier added in the just-completed mutate phase. */
6
+ recentlyAdded: Set<NodeId>;
7
+ /** NodeIds the mutate phase orphaned. The completion frontier excludes
8
+ * these — optimize phase collects. */
9
+ recentlyOrphaned: Set<NodeId>;
10
+ }
11
+ interface CompletionResult {
12
+ graph: Graph;
13
+ added: NodeId[];
14
+ wired: EdgeTriple[];
15
+ unresolved: Diagnostic[];
16
+ }
17
+ interface CompletionOptions {
18
+ seed?: CompletionSeed;
19
+ onDiagnostic?: (d: Diagnostic) => void;
20
+ }
21
+ /**
22
+ * Walk graph, query registry for missing transitive deps, wire edges.
23
+ * Monotone-additive: returned graph ⊇ input graph (no removals).
24
+ */
25
+ declare function completeTransitives(graph: Graph, registry: RegistryAdapter, options?: CompletionOptions): Promise<CompletionResult>;
26
+
27
+ /**
28
+ * Walk consumer → root via incoming-edge BFS.
29
+ * Returns nodes in BFS order: consumer first, deeper ancestors last.
30
+ * Cycles tolerated via `seen`.
31
+ */
32
+ declare function ancestorsOf(graph: Graph, consumer: NodeId): Node[];
33
+ /**
34
+ * Find-up resolve per ADR-0023 §5.1.
35
+ *
36
+ * Returns the closest-ancestor satisfying node, or undefined if either
37
+ * (a) no ancestor declares `name` at all → caller may install nested at the
38
+ * consumer's level, or
39
+ * (b) the closest ancestor that declares `name` does so with a conflicting
40
+ * range → "block hoist", caller installs nested fallback (npm-3 style).
41
+ *
42
+ * Tiebreaker:
43
+ * 1. Highest semver-comparable version wins (`semver.rcompare`).
44
+ * 2. On version tie, lowest NodeId lex order wins.
45
+ *
46
+ * `depKind` is part of the §5.1 normative signature but does NOT affect the
47
+ * algorithm body in v1: every dep-kind (dep / dev / optional / peer) follows
48
+ * the same closest-ancestor reuse + block-hoist contract. The parameter is
49
+ * carried verbatim so future kind-filtered hoist policies (e.g. peer-deps
50
+ * needing a stricter find-up, or optional-deps allowed to silently fail
51
+ * differently from regular deps) can branch on it without a signature
52
+ * migration. Per the ADR §5.1 pseudocode body and the v1 normative scope, no
53
+ * kind-specific branch is taken yet.
54
+ */
55
+ declare function resolveFindUp(graph: Graph, consumerId: NodeId, name: string, range: string, depKind: EdgeKind): NodeId | undefined;
56
+
57
+ type CompletionDiagnosticCode = 'COMPLETION_NODE_ADDED' | 'COMPLETION_EDGE_RESOLVED' | 'COMPLETION_UNRESOLVED' | 'COMPLETION_NODE_UNKNOWN' | 'COMPLETION_VERSION_UNKNOWN' | 'COMPLETION_PEER_CONTEXT_INCOMPLETE';
58
+ interface CompletionDiagnostic extends Diagnostic {
59
+ code: CompletionDiagnosticCode;
60
+ }
61
+ declare function completionNodeAdded(nodeId: NodeId): CompletionDiagnostic;
62
+ declare function completionEdgeResolved(triple: EdgeTriple): CompletionDiagnostic;
63
+ declare function completionUnresolved(consumer: NodeId, depName: string, depRange: string): CompletionDiagnostic;
64
+ declare function completionNodeUnknown(nodeId: NodeId): CompletionDiagnostic;
65
+ declare function completionVersionUnknown(nodeId: NodeId): CompletionDiagnostic;
66
+ declare function completionPeerContextIncomplete(nodeId: NodeId, peerName: string, peerRange: string): CompletionDiagnostic;
67
+
68
+ export { type CompletionDiagnostic, type CompletionDiagnosticCode, type CompletionOptions, type CompletionResult, type CompletionSeed, ancestorsOf, completeTransitives, completionEdgeResolved, completionNodeAdded, completionNodeUnknown, completionPeerContextIncomplete, completionUnresolved, completionVersionUnknown, resolveFindUp };
@@ -0,0 +1,298 @@
1
+ import 'crypto';
2
+ import 'buffer';
3
+ import semver from 'semver';
4
+
5
+ // src/main/ts/errors.ts
6
+
7
+ // src/main/ts/graph.ts
8
+ function serializeNodeId(name, version, peerContext, patch) {
9
+ const base = toTarballKey({ name, version});
10
+ if (peerContext.length === 0) return base;
11
+ return base + peerContext.map((p) => `(${p})`).join("");
12
+ }
13
+ function toTarballKey(inputs) {
14
+ const slots = [];
15
+ return slots.length === 0 ? `${inputs.name}@${inputs.version}` : `${inputs.name}@${inputs.version}+${slots.sort(cmpStr).join("+")}`;
16
+ }
17
+ var cmpStr = (a, b) => a < b ? -1 : a > b ? 1 : 0;
18
+ var cmpStr2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
19
+ function ancestorsOf(graph, consumer) {
20
+ const consumerNode = graph.getNode(consumer);
21
+ if (consumerNode === void 0) return [];
22
+ const result = [consumerNode];
23
+ const seen = /* @__PURE__ */ new Set([consumer]);
24
+ const queue = [consumer];
25
+ while (queue.length > 0) {
26
+ const cur = queue.shift();
27
+ for (const edge of graph.in(cur)) {
28
+ if (seen.has(edge.src)) continue;
29
+ const srcNode = graph.getNode(edge.src);
30
+ if (srcNode === void 0) continue;
31
+ seen.add(edge.src);
32
+ result.push(srcNode);
33
+ queue.push(edge.src);
34
+ }
35
+ }
36
+ return result;
37
+ }
38
+ function resolveFindUp(graph, consumerId, name, range, depKind) {
39
+ const path = ancestorsOf(graph, consumerId);
40
+ for (const ancestor of path) {
41
+ const candidates = [];
42
+ for (const edge of graph.out(ancestor.id)) {
43
+ const dst = graph.getNode(edge.dst);
44
+ if (dst === void 0) continue;
45
+ if (dst.name === name) candidates.push(dst);
46
+ }
47
+ if (candidates.length === 0) continue;
48
+ const satisfying = candidates.filter((c) => safeSatisfies(c.version, range));
49
+ if (satisfying.length === 0) {
50
+ return void 0;
51
+ }
52
+ satisfying.sort((a, b) => {
53
+ const v = semverRcompareSafe(a.version, b.version);
54
+ if (v !== 0) return v;
55
+ return cmpStr2(a.id, b.id);
56
+ });
57
+ return satisfying[0].id;
58
+ }
59
+ return void 0;
60
+ }
61
+ function safeSatisfies(version, range) {
62
+ try {
63
+ return semver.satisfies(version, range);
64
+ } catch {
65
+ return false;
66
+ }
67
+ }
68
+ function semverRcompareSafe(a, b) {
69
+ const va = semver.valid(a);
70
+ const vb = semver.valid(b);
71
+ if (va !== null && vb !== null) return semver.rcompare(a, b);
72
+ return cmpStr2(b, a);
73
+ }
74
+
75
+ // src/main/ts/complete/diagnostics.ts
76
+ function completionNodeAdded(nodeId) {
77
+ return {
78
+ code: "COMPLETION_NODE_ADDED",
79
+ severity: "info",
80
+ subject: nodeId,
81
+ message: `completion added ${nodeId}`
82
+ };
83
+ }
84
+ function completionEdgeResolved(triple) {
85
+ return {
86
+ code: "COMPLETION_EDGE_RESOLVED",
87
+ severity: "info",
88
+ subject: triple,
89
+ message: `wired ${triple.src} \u2192${triple.kind} ${triple.dst} via find-up reuse`
90
+ };
91
+ }
92
+ function completionUnresolved(consumer, depName, depRange) {
93
+ return {
94
+ code: "COMPLETION_UNRESOLVED",
95
+ severity: "warning",
96
+ subject: consumer,
97
+ message: `cannot resolve ${depName}@${depRange} for consumer ${consumer}`
98
+ };
99
+ }
100
+ function completionNodeUnknown(nodeId) {
101
+ return {
102
+ code: "COMPLETION_NODE_UNKNOWN",
103
+ severity: "warning",
104
+ subject: nodeId,
105
+ message: `registry has no packument for ${nodeId}`
106
+ };
107
+ }
108
+ function completionVersionUnknown(nodeId) {
109
+ return {
110
+ code: "COMPLETION_VERSION_UNKNOWN",
111
+ severity: "warning",
112
+ subject: nodeId,
113
+ message: `packument lacks version for ${nodeId}`
114
+ };
115
+ }
116
+ function completionPeerContextIncomplete(nodeId, peerName, peerRange) {
117
+ return {
118
+ code: "COMPLETION_PEER_CONTEXT_INCOMPLETE",
119
+ severity: "warning",
120
+ subject: nodeId,
121
+ message: `peer ${peerName}@${peerRange} unresolved at completion for ${nodeId}`
122
+ };
123
+ }
124
+
125
+ // src/main/ts/complete/tree-complete.ts
126
+ var EMPTY_SEED = {
127
+ recentlyAdded: /* @__PURE__ */ new Set(),
128
+ recentlyOrphaned: /* @__PURE__ */ new Set()
129
+ };
130
+ async function completeTransitives(graph, registry, options = {}) {
131
+ const seed = options.seed ?? EMPTY_SEED;
132
+ const onDiagnostic = options.onDiagnostic;
133
+ const visited = /* @__PURE__ */ new Set();
134
+ const added = [];
135
+ const wired = [];
136
+ const unresolved = [];
137
+ let currentGraph = graph;
138
+ const emit = (d) => {
139
+ unresolved.push(d);
140
+ if (onDiagnostic !== void 0) onDiagnostic(d);
141
+ };
142
+ const emitAndLand = (d) => {
143
+ emit(d);
144
+ currentGraph = currentGraph.mutate((m) => {
145
+ m.diagnostic(d);
146
+ }).graph;
147
+ };
148
+ const frontier = [];
149
+ for (const root of currentGraph.roots()) {
150
+ if (!seed.recentlyOrphaned.has(root)) frontier.push(root);
151
+ }
152
+ for (const id of seed.recentlyAdded) {
153
+ if (!seed.recentlyOrphaned.has(id)) frontier.push(id);
154
+ }
155
+ while (frontier.length > 0) {
156
+ const nodeId = frontier.shift();
157
+ if (visited.has(nodeId)) continue;
158
+ visited.add(nodeId);
159
+ const node = currentGraph.getNode(nodeId);
160
+ if (node === void 0) continue;
161
+ if (node.workspacePath !== void 0) {
162
+ for (const edge of currentGraph.out(nodeId)) {
163
+ if (!visited.has(edge.dst)) frontier.push(edge.dst);
164
+ }
165
+ continue;
166
+ }
167
+ const packument = await registry.packument(node.name);
168
+ if (packument === void 0) {
169
+ for (const edge of currentGraph.out(nodeId)) {
170
+ if (!visited.has(edge.dst)) frontier.push(edge.dst);
171
+ }
172
+ emitAndLand(completionNodeUnknown(nodeId));
173
+ continue;
174
+ }
175
+ const pv = packument.versions[node.version];
176
+ if (pv === void 0) {
177
+ for (const edge of currentGraph.out(nodeId)) {
178
+ if (!visited.has(edge.dst)) frontier.push(edge.dst);
179
+ }
180
+ emitAndLand(completionVersionUnknown(nodeId));
181
+ continue;
182
+ }
183
+ const depBuckets = [
184
+ { deps: pv.dependencies, kind: "dep" },
185
+ { deps: pv.devDependencies, kind: "dev" },
186
+ { deps: pv.optionalDependencies, kind: "optional" },
187
+ { deps: pv.peerDependencies, kind: "peer" }
188
+ ];
189
+ for (const { deps, kind } of depBuckets) {
190
+ if (deps === void 0) continue;
191
+ const depNames = Object.keys(deps).sort(cmpStr3);
192
+ for (const depName of depNames) {
193
+ const depRange = deps[depName];
194
+ if (alreadyWired(currentGraph, nodeId, depName, kind)) continue;
195
+ const targetId = resolveFindUp(currentGraph, nodeId, depName, depRange);
196
+ if (targetId !== void 0) {
197
+ if (kind === "peer") {
198
+ emitAndLand(completionPeerContextIncomplete(nodeId, depName, depRange));
199
+ continue;
200
+ }
201
+ const triple2 = { src: nodeId, dst: targetId, kind };
202
+ const resolvedDiag = completionEdgeResolved(triple2);
203
+ const result2 = currentGraph.mutate((m) => {
204
+ m.addEdge(nodeId, targetId, kind, { range: depRange });
205
+ m.diagnostic(resolvedDiag);
206
+ });
207
+ currentGraph = result2.graph;
208
+ wired.push(triple2);
209
+ emit(resolvedDiag);
210
+ if (!visited.has(targetId)) frontier.push(targetId);
211
+ continue;
212
+ }
213
+ const resolved = await registry.resolve(depName, depRange);
214
+ if (resolved === void 0) {
215
+ if (kind === "peer") {
216
+ emitAndLand(completionPeerContextIncomplete(nodeId, depName, depRange));
217
+ } else {
218
+ emitAndLand(completionUnresolved(nodeId, depName, depRange));
219
+ }
220
+ continue;
221
+ }
222
+ const newId = serializeNodeId(resolved.name, resolved.version, []);
223
+ const newNode = {
224
+ id: newId,
225
+ name: resolved.name,
226
+ version: resolved.version,
227
+ peerContext: []
228
+ };
229
+ const { inputs, payload } = projectPackumentVersion(resolved);
230
+ if (kind === "peer") {
231
+ emitAndLand(completionPeerContextIncomplete(nodeId, depName, depRange));
232
+ continue;
233
+ }
234
+ let alreadyAdded = false;
235
+ const nodeAddedDiag = completionNodeAdded(newId);
236
+ const result = currentGraph.mutate((m) => {
237
+ if (currentGraph.getNode(newId) === void 0) {
238
+ m.addNode(newNode);
239
+ m.setTarball(inputs, payload);
240
+ m.diagnostic(nodeAddedDiag);
241
+ } else {
242
+ alreadyAdded = true;
243
+ }
244
+ m.addEdge(nodeId, newId, kind, { range: depRange });
245
+ });
246
+ currentGraph = result.graph;
247
+ if (!alreadyAdded) {
248
+ added.push(newId);
249
+ emit(nodeAddedDiag);
250
+ }
251
+ const triple = { src: nodeId, dst: newId, kind };
252
+ wired.push(triple);
253
+ if (!visited.has(newId)) frontier.push(newId);
254
+ }
255
+ }
256
+ for (const edge of currentGraph.out(nodeId)) {
257
+ if (!visited.has(edge.dst)) frontier.push(edge.dst);
258
+ }
259
+ }
260
+ return {
261
+ graph: currentGraph,
262
+ added,
263
+ wired,
264
+ unresolved
265
+ };
266
+ }
267
+ function alreadyWired(graph, src, depName, kind) {
268
+ for (const edge of graph.out(src, kind)) {
269
+ const dst = graph.getNode(edge.dst);
270
+ if (dst !== void 0 && dst.name === depName) return true;
271
+ }
272
+ return false;
273
+ }
274
+ function projectPackumentVersion(pv) {
275
+ return {
276
+ inputs: {
277
+ name: pv.name,
278
+ version: pv.version
279
+ // patch is always undefined per §4.2 — completion does not synthesise patches.
280
+ },
281
+ payload: {
282
+ integrity: pv.integrity,
283
+ engines: pv.engines,
284
+ os: pv.os,
285
+ cpu: pv.cpu,
286
+ libc: pv.libc,
287
+ bin: pv.bin,
288
+ bundledDependencies: pv.bundledDependencies,
289
+ deprecated: pv.deprecated,
290
+ resolution: pv.tarball === void 0 ? void 0 : { type: "tarball", url: pv.tarball }
291
+ // license intentionally undefined — not carried on PackumentVersion;
292
+ // recipe-layer enrich may refine later per §4.2 footnote.
293
+ }
294
+ };
295
+ }
296
+ var cmpStr3 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
297
+
298
+ export { ancestorsOf, completeTransitives, completionEdgeResolved, completionNodeAdded, completionNodeUnknown, completionPeerContextIncomplete, completionUnresolved, completionVersionUnknown, resolveFindUp };
@@ -1,4 +1,4 @@
1
- import { D as Diagnostic, G as Graph } from '../graph-BzsItuAI.js';
1
+ import { D as Diagnostic, G as Graph } from '../graph-XpDkFSjz.js';
2
2
 
3
3
  interface BunTextParseOptions {
4
4
  }
@@ -98,9 +98,13 @@ function tarballKeyInputsOfNode(node) {
98
98
  };
99
99
  }
100
100
  var cmpStr = (a, b) => a < b ? -1 : a > b ? 1 : 0;
101
+ var cmpAlias = (a, b) => a === b ? 0 : a === void 0 ? -1 : b === void 0 ? 1 : cmpStr(a, b);
101
102
  var cmpEdgeBy = (end) => (a, b) => {
102
103
  const c = cmpStr(end === "dst" ? a.dst : a.src, end === "dst" ? b.dst : b.src);
103
- return c !== 0 ? c : cmpStr(a.kind, b.kind);
104
+ if (c !== 0) return c;
105
+ const k = cmpStr(a.kind, b.kind);
106
+ if (k !== 0) return k;
107
+ return cmpAlias(a.attrs?.alias, b.attrs?.alias);
104
108
  };
105
109
  function emptyState() {
106
110
  return {
@@ -136,7 +140,7 @@ function removeMatching(arr, pred) {
136
140
  arr.splice(i, 1);
137
141
  return true;
138
142
  }
139
- var tripleKey = (e) => `${e.src}\0${e.kind}\0${e.dst}`;
143
+ var tripleKey = (e) => `${e.src}\0${e.kind}\0${e.dst}\0${e.attrs?.alias ?? ""}`;
140
144
  function rebindNodeId(s, oldId, newId, newNode) {
141
145
  s.nodes.set(newId, newNode);
142
146
  s.nodes.delete(oldId);
@@ -146,7 +150,9 @@ function rebindNodeId(s, oldId, newId, newNode) {
146
150
  for (const e of outs) {
147
151
  const peerInc = s.incoming.get(e.dst);
148
152
  if (peerInc) {
149
- const idx = peerInc.findIndex((x) => x.src === oldId && x.kind === e.kind && x.dst === e.dst);
153
+ const idx = peerInc.findIndex(
154
+ (x) => x.src === oldId && x.kind === e.kind && x.dst === e.dst && x.attrs?.alias === e.attrs?.alias
155
+ );
150
156
  if (idx >= 0) peerInc[idx] = e;
151
157
  }
152
158
  }
@@ -156,11 +162,25 @@ function rebindNodeId(s, oldId, newId, newNode) {
156
162
  for (const e of ins) {
157
163
  const peerOut = s.outgoing.get(e.src);
158
164
  if (peerOut) {
159
- const idx = peerOut.findIndex((x) => x.src === e.src && x.kind === e.kind && x.dst === oldId);
165
+ const idx = peerOut.findIndex(
166
+ (x) => x.src === e.src && x.kind === e.kind && x.dst === oldId && x.attrs?.alias === e.attrs?.alias
167
+ );
160
168
  if (idx >= 0) peerOut[idx] = e;
161
169
  }
162
170
  }
163
171
  }
172
+ function protocolOf(range) {
173
+ const colonIdx = range.indexOf(":");
174
+ if (colonIdx <= 0) return void 0;
175
+ const prefix = range.slice(0, colonIdx);
176
+ return /^[a-z][a-z0-9+.-]*$/i.test(prefix) ? prefix : void 0;
177
+ }
178
+ function isPublishedSelfLink(edge) {
179
+ const range = edge.attrs?.range;
180
+ if (range === void 0) return false;
181
+ const proto = protocolOf(range);
182
+ return proto === void 0 || proto === "npm";
183
+ }
164
184
  function validate(s) {
165
185
  for (const d of s.diagnostics) {
166
186
  if (d.severity === "error") {
@@ -178,16 +198,26 @@ function validate(s) {
178
198
  }
179
199
  const k = tripleKey(e);
180
200
  if (seen.has(k)) {
181
- throw new GraphError("INVARIANT_VIOLATION", `duplicate edge: ${e.src} \u2192${e.kind} ${e.dst}`);
201
+ const aliasSuffix = e.attrs?.alias !== void 0 ? ` (alias=${e.attrs.alias})` : "";
202
+ throw new GraphError("INVARIANT_VIOLATION", `duplicate edge: ${e.src} \u2192${e.kind} ${e.dst}${aliasSuffix}`);
182
203
  }
183
204
  seen.add(k);
184
205
  }
185
206
  }
186
207
  for (const [id, node] of s.nodes) {
187
208
  if (node.workspacePath !== void 0) {
188
- const inc = s.incoming.get(id);
189
- const hasNonWorkspaceIncoming = inc?.some((edge) => s.nodes.get(edge.src)?.workspacePath === void 0) ?? false;
190
- if (hasNonWorkspaceIncoming) {
209
+ const inc = s.incoming.get(id) ?? [];
210
+ for (const edge of inc) {
211
+ if (s.nodes.get(edge.src)?.workspacePath !== void 0) continue;
212
+ if (isPublishedSelfLink(edge)) {
213
+ s.diagnostics.push({
214
+ code: "SEAL_PUBLISHED_SELF_LINK",
215
+ subject: id,
216
+ severity: "info",
217
+ message: `published self-link: ${edge.src} \u2192${edge.kind} ${id} (range ${edge.attrs?.range}) \u2014 published dependency resolved to co-located workspace`
218
+ });
219
+ continue;
220
+ }
191
221
  throw new GraphError("INVARIANT_VIOLATION", `workspace node has incoming edges: ${id}`);
192
222
  }
193
223
  }
@@ -468,8 +498,10 @@ var GraphImpl = class _GraphImpl {
468
498
  if (!next.nodes.has(src)) throw new GraphError("PATCH_REJECTED", `addEdge: src ${src} missing`);
469
499
  if (!next.nodes.has(dst)) throw new GraphError("PATCH_REJECTED", `addEdge: dst ${dst} missing`);
470
500
  const existing = next.outgoing.get(src) ?? [];
471
- if (existing.some((e2) => e2.dst === dst && e2.kind === kind)) {
472
- throw new GraphError("PATCH_REJECTED", `addEdge: duplicate ${src} \u2192${kind} ${dst}`);
501
+ const newAlias = attrs?.alias;
502
+ if (existing.some((e2) => e2.dst === dst && e2.kind === kind && e2.attrs?.alias === newAlias)) {
503
+ const aliasSuffix = newAlias !== void 0 ? ` (alias=${newAlias})` : "";
504
+ throw new GraphError("PATCH_REJECTED", `addEdge: duplicate ${src} \u2192${kind} ${dst}${aliasSuffix}`);
473
505
  }
474
506
  const e = attrs ? { src, dst, kind, attrs } : { src, dst, kind };
475
507
  pushTo(next.outgoing, src, e);
@@ -478,11 +510,15 @@ var GraphImpl = class _GraphImpl {
478
510
  },
479
511
  removeEdge(src, dst, kind) {
480
512
  const outs = next.outgoing.get(src);
481
- if (!outs || !removeMatching(outs, (e) => e.dst === dst && e.kind === kind)) {
513
+ let removedAlias;
514
+ const found = outs?.findIndex((e) => e.dst === dst && e.kind === kind) ?? -1;
515
+ if (!outs || found < 0) {
482
516
  throw new GraphError("PATCH_REJECTED", `removeEdge: ${src} \u2192${kind} ${dst} missing`);
483
517
  }
518
+ removedAlias = outs[found]?.attrs?.alias;
519
+ outs.splice(found, 1);
484
520
  const ins = next.incoming.get(dst);
485
- if (ins) removeMatching(ins, (e) => e.src === src && e.kind === kind);
521
+ if (ins) removeMatching(ins, (e) => e.src === src && e.kind === kind && e.attrs?.alias === removedAlias);
486
522
  applied.push({ kind: "edge-removed", subject: { src, dst, kind } });
487
523
  },
488
524
  replacePeerContext(id, peers) {
@@ -527,6 +563,12 @@ var GraphImpl = class _GraphImpl {
527
563
  throw new GraphError("PATCH_REJECTED", `removeTarball: ${key} missing`);
528
564
  }
529
565
  applied.push({ kind: "tarball-removed", subject: key });
566
+ },
567
+ // ADR-0023 §8.6 — write-side diagnostic emit. Append to the staged
568
+ // diagnostics list; the resulting Graph.diagnostics() surfaces it
569
+ // once mutate() settles. Same append semantics as Builder.diagnostic.
570
+ diagnostic(d) {
571
+ next.diagnostics.push(d);
530
572
  }
531
573
  };
532
574
  transaction(m);
@@ -1,4 +1,4 @@
1
- import { D as Diagnostic, G as Graph } from '../graph-BzsItuAI.js';
1
+ import { D as Diagnostic, G as Graph } from '../graph-XpDkFSjz.js';
2
2
 
3
3
  interface Npm1ParseOptions {
4
4
  }
@@ -99,9 +99,13 @@ function tarballKeyInputsOfNode(node) {
99
99
  };
100
100
  }
101
101
  var cmpStr = (a, b) => a < b ? -1 : a > b ? 1 : 0;
102
+ var cmpAlias = (a, b) => a === b ? 0 : a === void 0 ? -1 : b === void 0 ? 1 : cmpStr(a, b);
102
103
  var cmpEdgeBy = (end) => (a, b) => {
103
104
  const c = cmpStr(end === "dst" ? a.dst : a.src, end === "dst" ? b.dst : b.src);
104
- return c !== 0 ? c : cmpStr(a.kind, b.kind);
105
+ if (c !== 0) return c;
106
+ const k = cmpStr(a.kind, b.kind);
107
+ if (k !== 0) return k;
108
+ return cmpAlias(a.attrs?.alias, b.attrs?.alias);
105
109
  };
106
110
  function emptyState() {
107
111
  return {
@@ -137,7 +141,7 @@ function removeMatching(arr, pred) {
137
141
  arr.splice(i, 1);
138
142
  return true;
139
143
  }
140
- var tripleKey = (e) => `${e.src}\0${e.kind}\0${e.dst}`;
144
+ var tripleKey = (e) => `${e.src}\0${e.kind}\0${e.dst}\0${e.attrs?.alias ?? ""}`;
141
145
  function rebindNodeId(s, oldId, newId, newNode) {
142
146
  s.nodes.set(newId, newNode);
143
147
  s.nodes.delete(oldId);
@@ -147,7 +151,9 @@ function rebindNodeId(s, oldId, newId, newNode) {
147
151
  for (const e of outs) {
148
152
  const peerInc = s.incoming.get(e.dst);
149
153
  if (peerInc) {
150
- const idx = peerInc.findIndex((x) => x.src === oldId && x.kind === e.kind && x.dst === e.dst);
154
+ const idx = peerInc.findIndex(
155
+ (x) => x.src === oldId && x.kind === e.kind && x.dst === e.dst && x.attrs?.alias === e.attrs?.alias
156
+ );
151
157
  if (idx >= 0) peerInc[idx] = e;
152
158
  }
153
159
  }
@@ -157,11 +163,25 @@ function rebindNodeId(s, oldId, newId, newNode) {
157
163
  for (const e of ins) {
158
164
  const peerOut = s.outgoing.get(e.src);
159
165
  if (peerOut) {
160
- const idx = peerOut.findIndex((x) => x.src === e.src && x.kind === e.kind && x.dst === oldId);
166
+ const idx = peerOut.findIndex(
167
+ (x) => x.src === e.src && x.kind === e.kind && x.dst === oldId && x.attrs?.alias === e.attrs?.alias
168
+ );
161
169
  if (idx >= 0) peerOut[idx] = e;
162
170
  }
163
171
  }
164
172
  }
173
+ function protocolOf(range) {
174
+ const colonIdx = range.indexOf(":");
175
+ if (colonIdx <= 0) return void 0;
176
+ const prefix = range.slice(0, colonIdx);
177
+ return /^[a-z][a-z0-9+.-]*$/i.test(prefix) ? prefix : void 0;
178
+ }
179
+ function isPublishedSelfLink(edge) {
180
+ const range = edge.attrs?.range;
181
+ if (range === void 0) return false;
182
+ const proto = protocolOf(range);
183
+ return proto === void 0 || proto === "npm";
184
+ }
165
185
  function validate(s) {
166
186
  for (const d of s.diagnostics) {
167
187
  if (d.severity === "error") {
@@ -179,16 +199,26 @@ function validate(s) {
179
199
  }
180
200
  const k = tripleKey(e);
181
201
  if (seen.has(k)) {
182
- throw new GraphError("INVARIANT_VIOLATION", `duplicate edge: ${e.src} \u2192${e.kind} ${e.dst}`);
202
+ const aliasSuffix = e.attrs?.alias !== void 0 ? ` (alias=${e.attrs.alias})` : "";
203
+ throw new GraphError("INVARIANT_VIOLATION", `duplicate edge: ${e.src} \u2192${e.kind} ${e.dst}${aliasSuffix}`);
183
204
  }
184
205
  seen.add(k);
185
206
  }
186
207
  }
187
208
  for (const [id, node] of s.nodes) {
188
209
  if (node.workspacePath !== void 0) {
189
- const inc = s.incoming.get(id);
190
- const hasNonWorkspaceIncoming = inc?.some((edge) => s.nodes.get(edge.src)?.workspacePath === void 0) ?? false;
191
- if (hasNonWorkspaceIncoming) {
210
+ const inc = s.incoming.get(id) ?? [];
211
+ for (const edge of inc) {
212
+ if (s.nodes.get(edge.src)?.workspacePath !== void 0) continue;
213
+ if (isPublishedSelfLink(edge)) {
214
+ s.diagnostics.push({
215
+ code: "SEAL_PUBLISHED_SELF_LINK",
216
+ subject: id,
217
+ severity: "info",
218
+ message: `published self-link: ${edge.src} \u2192${edge.kind} ${id} (range ${edge.attrs?.range}) \u2014 published dependency resolved to co-located workspace`
219
+ });
220
+ continue;
221
+ }
192
222
  throw new GraphError("INVARIANT_VIOLATION", `workspace node has incoming edges: ${id}`);
193
223
  }
194
224
  }
@@ -469,8 +499,10 @@ var GraphImpl = class _GraphImpl {
469
499
  if (!next.nodes.has(src)) throw new GraphError("PATCH_REJECTED", `addEdge: src ${src} missing`);
470
500
  if (!next.nodes.has(dst)) throw new GraphError("PATCH_REJECTED", `addEdge: dst ${dst} missing`);
471
501
  const existing = next.outgoing.get(src) ?? [];
472
- if (existing.some((e2) => e2.dst === dst && e2.kind === kind)) {
473
- throw new GraphError("PATCH_REJECTED", `addEdge: duplicate ${src} \u2192${kind} ${dst}`);
502
+ const newAlias = attrs?.alias;
503
+ if (existing.some((e2) => e2.dst === dst && e2.kind === kind && e2.attrs?.alias === newAlias)) {
504
+ const aliasSuffix = newAlias !== void 0 ? ` (alias=${newAlias})` : "";
505
+ throw new GraphError("PATCH_REJECTED", `addEdge: duplicate ${src} \u2192${kind} ${dst}${aliasSuffix}`);
474
506
  }
475
507
  const e = attrs ? { src, dst, kind, attrs } : { src, dst, kind };
476
508
  pushTo(next.outgoing, src, e);
@@ -479,11 +511,15 @@ var GraphImpl = class _GraphImpl {
479
511
  },
480
512
  removeEdge(src, dst, kind) {
481
513
  const outs = next.outgoing.get(src);
482
- if (!outs || !removeMatching(outs, (e) => e.dst === dst && e.kind === kind)) {
514
+ let removedAlias;
515
+ const found = outs?.findIndex((e) => e.dst === dst && e.kind === kind) ?? -1;
516
+ if (!outs || found < 0) {
483
517
  throw new GraphError("PATCH_REJECTED", `removeEdge: ${src} \u2192${kind} ${dst} missing`);
484
518
  }
519
+ removedAlias = outs[found]?.attrs?.alias;
520
+ outs.splice(found, 1);
485
521
  const ins = next.incoming.get(dst);
486
- if (ins) removeMatching(ins, (e) => e.src === src && e.kind === kind);
522
+ if (ins) removeMatching(ins, (e) => e.src === src && e.kind === kind && e.attrs?.alias === removedAlias);
487
523
  applied.push({ kind: "edge-removed", subject: { src, dst, kind } });
488
524
  },
489
525
  replacePeerContext(id, peers) {
@@ -528,6 +564,12 @@ var GraphImpl = class _GraphImpl {
528
564
  throw new GraphError("PATCH_REJECTED", `removeTarball: ${key} missing`);
529
565
  }
530
566
  applied.push({ kind: "tarball-removed", subject: key });
567
+ },
568
+ // ADR-0023 §8.6 — write-side diagnostic emit. Append to the staged
569
+ // diagnostics list; the resulting Graph.diagnostics() surfaces it
570
+ // once mutate() settles. Same append semantics as Builder.diagnostic.
571
+ diagnostic(d) {
572
+ next.diagnostics.push(d);
531
573
  }
532
574
  };
533
575
  transaction(m);