ruflo-graph-intelligence 0.1.0-alpha.1

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 (126) hide show
  1. package/.claude-flow/data/pending-insights.jsonl +30 -0
  2. package/dist/adapters/aidefence-suspicion-adapter.d.ts +40 -0
  3. package/dist/adapters/aidefence-suspicion-adapter.d.ts.map +1 -0
  4. package/dist/adapters/aidefence-suspicion-adapter.js +77 -0
  5. package/dist/adapters/aidefence-suspicion-adapter.js.map +1 -0
  6. package/dist/adapters/browser-causal-adapter.d.ts +83 -0
  7. package/dist/adapters/browser-causal-adapter.d.ts.map +1 -0
  8. package/dist/adapters/browser-causal-adapter.js +146 -0
  9. package/dist/adapters/browser-causal-adapter.js.map +1 -0
  10. package/dist/adapters/cost-attribution-adapter.d.ts +48 -0
  11. package/dist/adapters/cost-attribution-adapter.d.ts.map +1 -0
  12. package/dist/adapters/cost-attribution-adapter.js +95 -0
  13. package/dist/adapters/cost-attribution-adapter.js.map +1 -0
  14. package/dist/adapters/federation-trust-adapter.d.ts +49 -0
  15. package/dist/adapters/federation-trust-adapter.d.ts.map +1 -0
  16. package/dist/adapters/federation-trust-adapter.js +82 -0
  17. package/dist/adapters/federation-trust-adapter.js.map +1 -0
  18. package/dist/adapters/index.d.ts +16 -0
  19. package/dist/adapters/index.d.ts.map +1 -0
  20. package/dist/adapters/index.js +16 -0
  21. package/dist/adapters/index.js.map +1 -0
  22. package/dist/adapters/jujutsu-blast-radius-adapter.d.ts +46 -0
  23. package/dist/adapters/jujutsu-blast-radius-adapter.d.ts.map +1 -0
  24. package/dist/adapters/jujutsu-blast-radius-adapter.js +80 -0
  25. package/dist/adapters/jujutsu-blast-radius-adapter.js.map +1 -0
  26. package/dist/adapters/knowledge-graph-adapter.d.ts +41 -0
  27. package/dist/adapters/knowledge-graph-adapter.d.ts.map +1 -0
  28. package/dist/adapters/knowledge-graph-adapter.js +83 -0
  29. package/dist/adapters/knowledge-graph-adapter.js.map +1 -0
  30. package/dist/adapters/observability-span-adapter.d.ts +45 -0
  31. package/dist/adapters/observability-span-adapter.d.ts.map +1 -0
  32. package/dist/adapters/observability-span-adapter.js +97 -0
  33. package/dist/adapters/observability-span-adapter.js.map +1 -0
  34. package/dist/adapters/portfolio-cg-adapter.d.ts +60 -0
  35. package/dist/adapters/portfolio-cg-adapter.d.ts.map +1 -0
  36. package/dist/adapters/portfolio-cg-adapter.js +102 -0
  37. package/dist/adapters/portfolio-cg-adapter.js.map +1 -0
  38. package/dist/adapters/rag-memory-adapter.d.ts +49 -0
  39. package/dist/adapters/rag-memory-adapter.d.ts.map +1 -0
  40. package/dist/adapters/rag-memory-adapter.js +86 -0
  41. package/dist/adapters/rag-memory-adapter.js.map +1 -0
  42. package/dist/application/federation-client.d.ts +54 -0
  43. package/dist/application/federation-client.d.ts.map +1 -0
  44. package/dist/application/federation-client.js +101 -0
  45. package/dist/application/federation-client.js.map +1 -0
  46. package/dist/application/federation-server.d.ts +38 -0
  47. package/dist/application/federation-server.d.ts.map +1 -0
  48. package/dist/application/federation-server.js +127 -0
  49. package/dist/application/federation-server.js.map +1 -0
  50. package/dist/application/streaming-bridge.d.ts +62 -0
  51. package/dist/application/streaming-bridge.d.ts.map +1 -0
  52. package/dist/application/streaming-bridge.js +101 -0
  53. package/dist/application/streaming-bridge.js.map +1 -0
  54. package/dist/domain/adapter.d.ts +58 -0
  55. package/dist/domain/adapter.d.ts.map +1 -0
  56. package/dist/domain/adapter.js +43 -0
  57. package/dist/domain/adapter.js.map +1 -0
  58. package/dist/domain/federation-protocol.d.ts +857 -0
  59. package/dist/domain/federation-protocol.d.ts.map +1 -0
  60. package/dist/domain/federation-protocol.js +72 -0
  61. package/dist/domain/federation-protocol.js.map +1 -0
  62. package/dist/domain/signed-artifact.d.ts +429 -0
  63. package/dist/domain/signed-artifact.d.ts.map +1 -0
  64. package/dist/domain/signed-artifact.js +57 -0
  65. package/dist/domain/signed-artifact.js.map +1 -0
  66. package/dist/domain/types.d.ts +329 -0
  67. package/dist/domain/types.d.ts.map +1 -0
  68. package/dist/domain/types.js +165 -0
  69. package/dist/domain/types.js.map +1 -0
  70. package/dist/index.d.ts +31 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +37 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/infrastructure/jl-embed.d.ts +27 -0
  75. package/dist/infrastructure/jl-embed.d.ts.map +1 -0
  76. package/dist/infrastructure/jl-embed.js +79 -0
  77. package/dist/infrastructure/jl-embed.js.map +1 -0
  78. package/dist/infrastructure/solver-bridge.d.ts +73 -0
  79. package/dist/infrastructure/solver-bridge.d.ts.map +1 -0
  80. package/dist/infrastructure/solver-bridge.js +359 -0
  81. package/dist/infrastructure/solver-bridge.js.map +1 -0
  82. package/dist/infrastructure/witness-signer.d.ts +44 -0
  83. package/dist/infrastructure/witness-signer.d.ts.map +1 -0
  84. package/dist/infrastructure/witness-signer.js +158 -0
  85. package/dist/infrastructure/witness-signer.js.map +1 -0
  86. package/dist/mcp-tools/index.d.ts +27 -0
  87. package/dist/mcp-tools/index.d.ts.map +1 -0
  88. package/dist/mcp-tools/index.js +292 -0
  89. package/dist/mcp-tools/index.js.map +1 -0
  90. package/package.json +55 -0
  91. package/ruvector.db +0 -0
  92. package/src/adapters/aidefence-suspicion-adapter.ts +102 -0
  93. package/src/adapters/browser-causal-adapter.ts +193 -0
  94. package/src/adapters/cost-attribution-adapter.ts +123 -0
  95. package/src/adapters/federation-trust-adapter.ts +116 -0
  96. package/src/adapters/index.ts +87 -0
  97. package/src/adapters/jujutsu-blast-radius-adapter.ts +107 -0
  98. package/src/adapters/knowledge-graph-adapter.ts +110 -0
  99. package/src/adapters/observability-span-adapter.ts +123 -0
  100. package/src/adapters/portfolio-cg-adapter.ts +140 -0
  101. package/src/adapters/rag-memory-adapter.ts +117 -0
  102. package/src/application/federation-client.ts +147 -0
  103. package/src/application/federation-server.ts +158 -0
  104. package/src/application/streaming-bridge.ts +137 -0
  105. package/src/domain/adapter.ts +92 -0
  106. package/src/domain/federation-protocol.ts +95 -0
  107. package/src/domain/signed-artifact.ts +80 -0
  108. package/src/domain/types.ts +215 -0
  109. package/src/index.ts +105 -0
  110. package/src/infrastructure/jl-embed.ts +98 -0
  111. package/src/infrastructure/solver-bridge.ts +389 -0
  112. package/src/infrastructure/witness-signer.ts +209 -0
  113. package/src/mcp-tools/index.ts +316 -0
  114. package/tests/adapter-registry.test.ts +69 -0
  115. package/tests/browser-causal-adapter.test.ts +174 -0
  116. package/tests/mcp-tools.test.ts +169 -0
  117. package/tests/phase3-adapters.test.ts +206 -0
  118. package/tests/phase4-adapters.test.ts +158 -0
  119. package/tests/phase5-portfolio.test.ts +122 -0
  120. package/tests/phase6-adapters.test.ts +224 -0
  121. package/tests/phase6_5-streaming.test.ts +135 -0
  122. package/tests/phase7-signed-artifact.test.ts +238 -0
  123. package/tests/phase8-federation.test.ts +194 -0
  124. package/tests/solver-bridge.test.ts +255 -0
  125. package/tsconfig.json +21 -0
  126. package/vitest.config.ts +9 -0
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Portfolio Covariance Adapter (Wedge 8, ADR-123 Phase 5)
3
+ *
4
+ * `ruflo-neural-trader` does mean-variance optimisation: solve `Σ x = μ`
5
+ * where `Σ` is the symmetric positive-definite asset-covariance matrix and
6
+ * `μ` is the vector of expected returns. CG is the ideal target — upstream
7
+ * 1.7.0 benchmarks: **816 ns at n=256, 40-60× faster than Neumann**.
8
+ *
9
+ * This adapter exports the covariance matrix as a SparseMatrix so callers
10
+ * use `sublinear/solve` with `algorithm: 'cg'` and get the optimal weights.
11
+ * Unlike the PageRank wedges, this graph IS symmetric (Σ = Σᵀ) and SPD by
12
+ * construction.
13
+ */
14
+ import { createHash } from 'node:crypto';
15
+ import { getRegistry } from '../domain/adapter.js';
16
+ export function portfolioGraphId(portfolioId) {
17
+ return `ruflo-neural-trader:covariance:${portfolioId}`;
18
+ }
19
+ export class PortfolioCovarianceAdapter {
20
+ graphId;
21
+ ownerPlugin = 'ruflo-neural-trader';
22
+ requiresPreprocessing = false;
23
+ source;
24
+ portfolioId;
25
+ ridge;
26
+ constructor(options) {
27
+ this.source = options.source;
28
+ this.portfolioId = options.portfolioId;
29
+ this.ridge = options.ridge ?? 1e-6;
30
+ this.graphId = portfolioGraphId(this.portfolioId);
31
+ }
32
+ async exportAsSparseMatrix(options) {
33
+ const covEntries = await this.source.listCovarianceEntries(this.portfolioId);
34
+ const assetSet = new Set();
35
+ for (const e of covEntries) {
36
+ assetSet.add(e.assetA);
37
+ assetSet.add(e.assetB);
38
+ }
39
+ if (options?.nodeFilter) {
40
+ for (const a of [...assetSet])
41
+ if (!options.nodeFilter.has(a))
42
+ assetSet.delete(a);
43
+ }
44
+ const assets = [...assetSet].sort();
45
+ const nodeIndex = {};
46
+ assets.forEach((a, i) => (nodeIndex[a] = i));
47
+ // Symmetrise. If only Σ[A,B] is provided, also emit Σ[B,A] with the same value.
48
+ const sym = new Map();
49
+ for (const e of covEntries) {
50
+ const r = nodeIndex[e.assetA];
51
+ const c = nodeIndex[e.assetB];
52
+ if (r === undefined || c === undefined)
53
+ continue;
54
+ const k1 = `${r},${c}`;
55
+ const k2 = `${c},${r}`;
56
+ sym.set(k1, e.covariance);
57
+ sym.set(k2, e.covariance);
58
+ }
59
+ const entries = [];
60
+ for (const [key, v] of sym) {
61
+ const [rStr, cStr] = key.split(',');
62
+ const r = Number(rStr);
63
+ const c = Number(cStr);
64
+ if (r === c)
65
+ continue;
66
+ entries.push({ row: r, col: c, value: v });
67
+ }
68
+ // Diagonal: existing variance value (if provided) PLUS ridge — keeps SPD
69
+ // even when the empirical Σ is rank-deficient.
70
+ for (let i = 0; i < assets.length; i++) {
71
+ const provided = sym.get(`${i},${i}`) ?? 0;
72
+ entries.push({ row: i, col: i, value: provided + this.ridge });
73
+ }
74
+ return {
75
+ graphId: this.graphId,
76
+ size: assets.length,
77
+ entries,
78
+ nodeIndex,
79
+ indexNode: assets,
80
+ capturedAt: new Date().toISOString(),
81
+ contentHash: hashContent(this.graphId, entries),
82
+ };
83
+ }
84
+ /** Fetch expected returns aligned with the matrix's node order. */
85
+ async expectedReturnsVector(matrix) {
86
+ const expected = await this.source.listExpectedReturns(this.portfolioId);
87
+ return matrix.indexNode.map((a) => expected[a] ?? 0);
88
+ }
89
+ }
90
+ export function registerPortfolioCovarianceAdapter(options) {
91
+ const adapter = new PortfolioCovarianceAdapter(options);
92
+ (options.registry ?? getRegistry()).register(adapter);
93
+ return adapter;
94
+ }
95
+ function hashContent(graphId, entries) {
96
+ const h = createHash('sha256');
97
+ h.update(graphId);
98
+ for (const e of entries)
99
+ h.update(`|${e.row},${e.col},${e.value.toFixed(8)}`);
100
+ return h.digest('hex');
101
+ }
102
+ //# sourceMappingURL=portfolio-cg-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portfolio-cg-adapter.js","sourceRoot":"","sources":["../../src/adapters/portfolio-cg-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * RAG Memory Adapter (Wedge 5, ADR-123 Phase 4)
3
+ *
4
+ * `ruflo-rag-memory` ships Graph-RAG multi-hop retrieval. This adapter
5
+ * exports the chunk-connectivity graph so personalized PR seeded by the
6
+ * query embedding ranks candidate chunks globally — graph-aware retrieval
7
+ * beyond flat top-k MMR rerank.
8
+ *
9
+ * The seedNodes for personalized PR come from the caller's query side
10
+ * (`sublinear/page-rank-entry` already accepts seedNodes). This adapter
11
+ * just exposes the underlying chunk graph.
12
+ */
13
+ import type { SparseMatrix } from '../domain/types.js';
14
+ import type { SublinearAdapter, AdapterRegistry } from '../domain/adapter.js';
15
+ export interface ChunkEdge {
16
+ fromChunkId: string;
17
+ toChunkId: string;
18
+ /** Similarity weight in [0, 1] — typically cosine similarity of chunk embeddings. */
19
+ similarity: number;
20
+ }
21
+ export interface RagMemorySource {
22
+ listChunkEdges(namespace?: string): Promise<readonly ChunkEdge[]>;
23
+ }
24
+ export interface RagMemoryAdapterOptions {
25
+ source: RagMemorySource;
26
+ namespace?: string;
27
+ /** Minimum similarity to include an edge. Default 0.5. */
28
+ similarityFloor?: number;
29
+ /** DD safety margin. Default 0.25. */
30
+ ddSafetyMargin?: number;
31
+ }
32
+ export declare function ragMemoryGraphId(namespace?: string): string;
33
+ export declare class RagMemoryAdapter implements SublinearAdapter {
34
+ readonly graphId: string;
35
+ readonly ownerPlugin = "ruflo-rag-memory";
36
+ readonly requiresPreprocessing = false;
37
+ private readonly source;
38
+ private readonly namespace?;
39
+ private readonly similarityFloor;
40
+ private readonly ddSafetyMargin;
41
+ constructor(options: RagMemoryAdapterOptions);
42
+ exportAsSparseMatrix(options?: {
43
+ nodeFilter?: ReadonlySet<string>;
44
+ }): Promise<SparseMatrix>;
45
+ }
46
+ export declare function registerRagMemoryAdapter(options: RagMemoryAdapterOptions & {
47
+ registry?: AdapterRegistry;
48
+ }): RagMemoryAdapter;
49
+ //# sourceMappingURL=rag-memory-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag-memory-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/rag-memory-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG9E,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,SAAS,EAAE,CAAC,CAAC;CACnE;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAI3D;AAED,qBAAa,gBAAiB,YAAW,gBAAgB;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,sBAAsB;IAC1C,QAAQ,CAAC,qBAAqB,SAAS;IAEvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,OAAO,EAAE,uBAAuB;IAQtC,oBAAoB,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CAuClG;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,uBAAuB,GAAG;IAAE,QAAQ,CAAC,EAAE,eAAe,CAAA;CAAE,GAChE,gBAAgB,CAIlB"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * RAG Memory Adapter (Wedge 5, ADR-123 Phase 4)
3
+ *
4
+ * `ruflo-rag-memory` ships Graph-RAG multi-hop retrieval. This adapter
5
+ * exports the chunk-connectivity graph so personalized PR seeded by the
6
+ * query embedding ranks candidate chunks globally — graph-aware retrieval
7
+ * beyond flat top-k MMR rerank.
8
+ *
9
+ * The seedNodes for personalized PR come from the caller's query side
10
+ * (`sublinear/page-rank-entry` already accepts seedNodes). This adapter
11
+ * just exposes the underlying chunk graph.
12
+ */
13
+ import { createHash } from 'node:crypto';
14
+ import { getRegistry } from '../domain/adapter.js';
15
+ export function ragMemoryGraphId(namespace) {
16
+ return namespace
17
+ ? `ruflo-rag-memory:chunks:${namespace}`
18
+ : 'ruflo-rag-memory:chunks:default';
19
+ }
20
+ export class RagMemoryAdapter {
21
+ graphId;
22
+ ownerPlugin = 'ruflo-rag-memory';
23
+ requiresPreprocessing = false;
24
+ source;
25
+ namespace;
26
+ similarityFloor;
27
+ ddSafetyMargin;
28
+ constructor(options) {
29
+ this.source = options.source;
30
+ this.namespace = options.namespace;
31
+ this.similarityFloor = options.similarityFloor ?? 0.5;
32
+ this.ddSafetyMargin = options.ddSafetyMargin ?? 0.25;
33
+ this.graphId = ragMemoryGraphId(this.namespace);
34
+ }
35
+ async exportAsSparseMatrix(options) {
36
+ const edges = (await this.source.listChunkEdges(this.namespace)).filter((e) => e.similarity >= this.similarityFloor);
37
+ const chunkSet = new Set();
38
+ for (const e of edges) {
39
+ chunkSet.add(e.fromChunkId);
40
+ chunkSet.add(e.toChunkId);
41
+ }
42
+ if (options?.nodeFilter) {
43
+ for (const n of [...chunkSet])
44
+ if (!options.nodeFilter.has(n))
45
+ chunkSet.delete(n);
46
+ }
47
+ const chunks = [...chunkSet].sort();
48
+ const nodeIndex = {};
49
+ chunks.forEach((n, i) => (nodeIndex[n] = i));
50
+ const entries = [];
51
+ const rowSums = new Array(chunks.length).fill(0);
52
+ for (const e of edges) {
53
+ const r = nodeIndex[e.fromChunkId];
54
+ const c = nodeIndex[e.toChunkId];
55
+ if (r === undefined || c === undefined || r === c)
56
+ continue;
57
+ entries.push({ row: r, col: c, value: e.similarity });
58
+ rowSums[r] += e.similarity;
59
+ }
60
+ for (let i = 0; i < chunks.length; i++) {
61
+ entries.push({ row: i, col: i, value: rowSums[i] + this.ddSafetyMargin });
62
+ }
63
+ return {
64
+ graphId: this.graphId,
65
+ size: chunks.length,
66
+ entries,
67
+ nodeIndex,
68
+ indexNode: chunks,
69
+ capturedAt: new Date().toISOString(),
70
+ contentHash: hashContent(this.graphId, entries),
71
+ };
72
+ }
73
+ }
74
+ export function registerRagMemoryAdapter(options) {
75
+ const adapter = new RagMemoryAdapter(options);
76
+ (options.registry ?? getRegistry()).register(adapter);
77
+ return adapter;
78
+ }
79
+ function hashContent(graphId, entries) {
80
+ const h = createHash('sha256');
81
+ h.update(graphId);
82
+ for (const e of entries)
83
+ h.update(`|${e.row},${e.col},${e.value.toFixed(8)}`);
84
+ return h.digest('hex');
85
+ }
86
+ //# sourceMappingURL=rag-memory-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag-memory-adapter.js","sourceRoot":"","sources":["../../src/adapters/rag-memory-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Federation Client for PR Artifacts (Phase 8 — beyond-SOTA, ADR-123)
3
+ *
4
+ * Sends `pr_artifact_request` to peers, verifies inbound `pr_artifact_response`
5
+ * envelopes via Phase 7 verifier with the consumer's trust list, falls back
6
+ * to local recompute on stale/untrusted responses.
7
+ */
8
+ import type { FederationMessage, FederationTransport } from '../domain/federation-protocol.js';
9
+ import type { ArtifactVerificationResult } from '../domain/signed-artifact.js';
10
+ import type { PageRankResult } from '../domain/types.js';
11
+ export interface FederationClientOptions {
12
+ installationId: string;
13
+ transport: FederationTransport;
14
+ /** Public keys we trust. Empty = trust any valid signature. */
15
+ trustedPublicKeys?: string[];
16
+ }
17
+ export interface FetchPrResult {
18
+ /** How the result was obtained. */
19
+ origin: 'peer' | 'local-fallback' | 'stale-fallback' | 'untrusted-fallback';
20
+ result: PageRankResult;
21
+ /** If origin === 'peer', the verification report. */
22
+ verification?: ArtifactVerificationResult;
23
+ /** Optional reason when we fell back. */
24
+ fallbackReason?: string;
25
+ }
26
+ export declare class FederationClient {
27
+ private readonly installationId;
28
+ private readonly transport;
29
+ private readonly trustedPublicKeys;
30
+ constructor(options: FederationClientOptions);
31
+ /**
32
+ * Fetch a single-entry PR score for `nodeId` over `graphId`. Tries the
33
+ * peer first; on stale/untrusted/missing, falls back to local recompute.
34
+ */
35
+ fetchPageRank(input: {
36
+ peer: string;
37
+ graphId: string;
38
+ nodeId: string;
39
+ alpha?: number;
40
+ epsilon?: number;
41
+ seedNodes?: string[];
42
+ lastKnownGraphHash?: string;
43
+ lastKnownResultHash?: string;
44
+ }): Promise<FetchPrResult>;
45
+ private localCompute;
46
+ }
47
+ /**
48
+ * Helper: an in-process transport stitching a client to a server. Useful for
49
+ * testing the Phase 8 round-trip without spinning up real ADR-104 wiring.
50
+ */
51
+ export declare function inProcessTransport(server: {
52
+ handle: (msg: FederationMessage) => Promise<FederationMessage | null>;
53
+ }): FederationTransport;
54
+ //# sourceMappingURL=federation-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federation-client.d.ts","sourceRoot":"","sources":["../../src/application/federation-client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EAIpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,+DAA+D;IAC/D,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,oBAAoB,CAAC;IAC5E,MAAM,EAAE,cAAc,CAAC;IACvB,qDAAqD;IACrD,YAAY,CAAC,EAAE,0BAA0B,CAAC;IAC1C,yCAAyC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAW;gBAEjC,OAAO,EAAE,uBAAuB;IAM5C;;;OAGG;IACG,aAAa,CAAC,KAAK,EAAE;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B,GAAG,OAAO,CAAC,aAAa,CAAC;YA8CZ,YAAY;CAsB3B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;CAAE,GAAG,mBAAmB,CAUzI"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Federation Client for PR Artifacts (Phase 8 — beyond-SOTA, ADR-123)
3
+ *
4
+ * Sends `pr_artifact_request` to peers, verifies inbound `pr_artifact_response`
5
+ * envelopes via Phase 7 verifier with the consumer's trust list, falls back
6
+ * to local recompute on stale/untrusted responses.
7
+ */
8
+ import { verifyArtifact } from '../infrastructure/witness-signer.js';
9
+ import { runPageRank } from '../infrastructure/solver-bridge.js';
10
+ import { getRegistry } from '../domain/adapter.js';
11
+ export class FederationClient {
12
+ installationId;
13
+ transport;
14
+ trustedPublicKeys;
15
+ constructor(options) {
16
+ this.installationId = options.installationId;
17
+ this.transport = options.transport;
18
+ this.trustedPublicKeys = options.trustedPublicKeys ?? [];
19
+ }
20
+ /**
21
+ * Fetch a single-entry PR score for `nodeId` over `graphId`. Tries the
22
+ * peer first; on stale/untrusted/missing, falls back to local recompute.
23
+ */
24
+ async fetchPageRank(input) {
25
+ const request = {
26
+ type: 'pr_artifact_request',
27
+ fromInstallation: this.installationId,
28
+ graphId: input.graphId,
29
+ queryNode: input.nodeId,
30
+ alpha: input.alpha ?? 0.85,
31
+ epsilon: input.epsilon ?? 1e-3,
32
+ seedNodes: input.seedNodes ?? [],
33
+ lastKnownGraphHash: input.lastKnownGraphHash,
34
+ lastKnownResultHash: input.lastKnownResultHash,
35
+ };
36
+ const response = await this.transport.send(input.peer, request);
37
+ if (response && response.type === 'pr_artifact_response') {
38
+ const verification = verifyArtifact(response.envelope, {
39
+ trustedPublicKeys: this.trustedPublicKeys.length > 0 ? this.trustedPublicKeys : undefined,
40
+ });
41
+ if (verification.valid) {
42
+ return {
43
+ origin: 'peer',
44
+ result: response.envelope.payload.result,
45
+ verification,
46
+ };
47
+ }
48
+ return {
49
+ origin: 'untrusted-fallback',
50
+ result: await this.localCompute(input),
51
+ verification,
52
+ fallbackReason: verification.reason ?? 'verification failed',
53
+ };
54
+ }
55
+ if (response && response.type === 'pr_artifact_stale') {
56
+ return {
57
+ origin: 'stale-fallback',
58
+ result: await this.localCompute(input),
59
+ fallbackReason: response.reason,
60
+ };
61
+ }
62
+ // No usable response
63
+ return {
64
+ origin: 'local-fallback',
65
+ result: await this.localCompute(input),
66
+ fallbackReason: 'no usable response from peer',
67
+ };
68
+ }
69
+ async localCompute(input) {
70
+ const adapter = getRegistry().get(input.graphId);
71
+ if (!adapter) {
72
+ throw new Error(`localCompute: no adapter for graphId=${input.graphId}`);
73
+ }
74
+ const matrix = await adapter.exportAsSparseMatrix();
75
+ return runPageRank(matrix, {
76
+ graphId: input.graphId,
77
+ nodeId: input.nodeId,
78
+ alpha: input.alpha ?? 0.85,
79
+ epsilon: input.epsilon ?? 1e-3,
80
+ seedNodes: input.seedNodes ?? [],
81
+ maxComplexityClass: 'polynomial',
82
+ coherenceThreshold: 0,
83
+ });
84
+ }
85
+ }
86
+ /**
87
+ * Helper: an in-process transport stitching a client to a server. Useful for
88
+ * testing the Phase 8 round-trip without spinning up real ADR-104 wiring.
89
+ */
90
+ export function inProcessTransport(server) {
91
+ return {
92
+ async send(_to, msg) {
93
+ return server.handle(msg);
94
+ },
95
+ onMessage() {
96
+ // not used in the in-process variant
97
+ return () => { };
98
+ },
99
+ };
100
+ }
101
+ //# sourceMappingURL=federation-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federation-client.js","sourceRoot":"","sources":["../../src/application/federation-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Federation Server for PR Artifacts (Phase 8 — beyond-SOTA, ADR-123)
3
+ *
4
+ * Receives `pr_artifact_request` messages and serves either a fresh signed
5
+ * artifact (if the holder has one cached or computes one on demand) or a
6
+ * stale-rejection. The server uses Phase 7's sealArtifact for signing and
7
+ * Phase 2-6 adapters for graph access.
8
+ *
9
+ * Pluggable via FederationTransport so ADR-104's real wire layer fits in
10
+ * unchanged.
11
+ */
12
+ import { type WitnessKey } from '../infrastructure/witness-signer.js';
13
+ import type { FederationMessage, FederationTransport } from '../domain/federation-protocol.js';
14
+ export interface FederationServerOptions {
15
+ installationId: string;
16
+ witnessKey: WitnessKey;
17
+ witnessKeyId: string;
18
+ transport: FederationTransport;
19
+ /** Per-graph rate-limit budget — requests per peer per minute. */
20
+ rateLimitPerPeerPerMinute?: number;
21
+ }
22
+ export declare class FederationServer {
23
+ private readonly installationId;
24
+ private readonly witnessKey;
25
+ private readonly witnessKeyId;
26
+ private readonly transport;
27
+ private readonly rateLimit;
28
+ private rateBuckets;
29
+ private unsubscribe?;
30
+ constructor(options: FederationServerOptions);
31
+ start(): void;
32
+ stop(): void;
33
+ /** Public test seam — handles a single inbound message. */
34
+ handle(msg: FederationMessage): Promise<FederationMessage | null>;
35
+ private handleRequest;
36
+ private checkRate;
37
+ }
38
+ //# sourceMappingURL=federation-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federation-server.d.ts","sourceRoot":"","sources":["../../src/application/federation-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAGpF,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EAIpB,MAAM,kCAAkC,CAAC;AAE1C,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,kEAAkE;IAClE,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC;AAOD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,WAAW,CAAC,CAAa;gBAErB,OAAO,EAAE,uBAAuB;IAQ5C,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,IAAI;IAIZ,2DAA2D;IACrD,MAAM,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;YAKzD,aAAa;IA8E3B,OAAO,CAAC,SAAS;CAWlB"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Federation Server for PR Artifacts (Phase 8 — beyond-SOTA, ADR-123)
3
+ *
4
+ * Receives `pr_artifact_request` messages and serves either a fresh signed
5
+ * artifact (if the holder has one cached or computes one on demand) or a
6
+ * stale-rejection. The server uses Phase 7's sealArtifact for signing and
7
+ * Phase 2-6 adapters for graph access.
8
+ *
9
+ * Pluggable via FederationTransport so ADR-104's real wire layer fits in
10
+ * unchanged.
11
+ */
12
+ import { sealArtifact } from '../infrastructure/witness-signer.js';
13
+ import { runPageRank } from '../infrastructure/solver-bridge.js';
14
+ import { getRegistry } from '../domain/adapter.js';
15
+ export class FederationServer {
16
+ installationId;
17
+ witnessKey;
18
+ witnessKeyId;
19
+ transport;
20
+ rateLimit;
21
+ rateBuckets = new Map();
22
+ unsubscribe;
23
+ constructor(options) {
24
+ this.installationId = options.installationId;
25
+ this.witnessKey = options.witnessKey;
26
+ this.witnessKeyId = options.witnessKeyId;
27
+ this.transport = options.transport;
28
+ this.rateLimit = options.rateLimitPerPeerPerMinute ?? 60;
29
+ }
30
+ start() {
31
+ this.unsubscribe = this.transport.onMessage((m) => this.handle(m));
32
+ }
33
+ stop() {
34
+ this.unsubscribe?.();
35
+ }
36
+ /** Public test seam — handles a single inbound message. */
37
+ async handle(msg) {
38
+ if (msg.type !== 'pr_artifact_request')
39
+ return null;
40
+ return this.handleRequest(msg);
41
+ }
42
+ async handleRequest(req) {
43
+ // Rate-limit per peer
44
+ if (!this.checkRate(req.fromInstallation)) {
45
+ return {
46
+ type: 'pr_artifact_stale',
47
+ fromInstallation: this.installationId,
48
+ graphId: req.graphId,
49
+ currentGraphHash: 'rate-limited'.padEnd(64, '0'),
50
+ reason: 'rate limit exceeded',
51
+ };
52
+ }
53
+ const adapter = getRegistry().get(req.graphId);
54
+ if (!adapter) {
55
+ return {
56
+ type: 'pr_artifact_stale',
57
+ fromInstallation: this.installationId,
58
+ graphId: req.graphId,
59
+ currentGraphHash: '0'.repeat(64),
60
+ reason: `no adapter for graphId=${req.graphId}`,
61
+ };
62
+ }
63
+ const matrix = await adapter.exportAsSparseMatrix();
64
+ const currentGraphHash = matrix.contentHash ?? '0'.repeat(64);
65
+ // Stale-check: if the requester's lastKnownGraphHash differs, send stale
66
+ if (req.lastKnownGraphHash && req.lastKnownGraphHash !== currentGraphHash) {
67
+ return {
68
+ type: 'pr_artifact_stale',
69
+ fromInstallation: this.installationId,
70
+ graphId: req.graphId,
71
+ currentGraphHash,
72
+ reason: 'graph has changed since requester last cached',
73
+ };
74
+ }
75
+ if (!req.queryNode) {
76
+ return {
77
+ type: 'pr_artifact_stale',
78
+ fromInstallation: this.installationId,
79
+ graphId: req.graphId,
80
+ currentGraphHash,
81
+ reason: 'full-vector requests not yet supported (Phase 8 only)',
82
+ };
83
+ }
84
+ // Compute and seal
85
+ const prResult = runPageRank(matrix, {
86
+ graphId: req.graphId,
87
+ nodeId: req.queryNode,
88
+ alpha: req.alpha,
89
+ epsilon: req.epsilon,
90
+ seedNodes: req.seedNodes,
91
+ maxComplexityClass: 'polynomial',
92
+ coherenceThreshold: 0,
93
+ });
94
+ const { envelope } = sealArtifact({
95
+ installationId: this.installationId,
96
+ witnessKeyId: this.witnessKeyId,
97
+ graphId: req.graphId,
98
+ graphHash: currentGraphHash,
99
+ graphTimestamp: matrix.capturedAt,
100
+ algorithm: 'forward-push',
101
+ alpha: req.alpha,
102
+ epsilon: req.epsilon,
103
+ queryNode: req.queryNode,
104
+ seedNodes: req.seedNodes,
105
+ result: prResult,
106
+ witnessKey: this.witnessKey,
107
+ });
108
+ return {
109
+ type: 'pr_artifact_response',
110
+ fromInstallation: this.installationId,
111
+ envelope,
112
+ };
113
+ }
114
+ checkRate(peer) {
115
+ const now = Date.now();
116
+ const bucket = this.rateBuckets.get(peer);
117
+ if (!bucket || now >= bucket.resetAt) {
118
+ this.rateBuckets.set(peer, { count: 1, resetAt: now + 60_000 });
119
+ return true;
120
+ }
121
+ if (bucket.count >= this.rateLimit)
122
+ return false;
123
+ bucket.count++;
124
+ return true;
125
+ }
126
+ }
127
+ //# sourceMappingURL=federation-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federation-server.js","sourceRoot":"","sources":["../../src/application/federation-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAmB,MAAM,qCAAqC,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAuBnD,MAAM,OAAO,gBAAgB;IACV,cAAc,CAAS;IACvB,UAAU,CAAa;IACvB,YAAY,CAAS;IACrB,SAAS,CAAsB;IAC/B,SAAS,CAAS;IAC3B,WAAW,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC5C,WAAW,CAAc;IAEjC,YAAY,OAAgC;QAC1C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,yBAAyB,IAAI,EAAE,CAAC;IAC3D,CAAC;IAED,KAAK;QACH,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,IAAI;QACF,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;IACvB,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,MAAM,CAAC,GAAsB;QACjC,IAAI,GAAG,CAAC,IAAI,KAAK,qBAAqB;YAAE,OAAO,IAAI,CAAC;QACpD,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,GAAsB;QAChD,sBAAsB;QACtB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC1C,OAAO;gBACL,IAAI,EAAE,mBAAmB;gBACzB,gBAAgB,EAAE,IAAI,CAAC,cAAc;gBACrC,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,gBAAgB,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC;gBAChD,MAAM,EAAE,qBAAqB;aACJ,CAAC;QAC9B,CAAC;QAED,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;gBACL,IAAI,EAAE,mBAAmB;gBACzB,gBAAgB,EAAE,IAAI,CAAC,cAAc;gBACrC,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAChC,MAAM,EAAE,0BAA0B,GAAG,CAAC,OAAO,EAAE;aACtB,CAAC;QAC9B,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,EAAE,CAAC;QACpD,MAAM,gBAAgB,GAAG,MAAM,CAAC,WAAW,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAE9D,yEAAyE;QACzE,IAAI,GAAG,CAAC,kBAAkB,IAAI,GAAG,CAAC,kBAAkB,KAAK,gBAAgB,EAAE,CAAC;YAC1E,OAAO;gBACL,IAAI,EAAE,mBAAmB;gBACzB,gBAAgB,EAAE,IAAI,CAAC,cAAc;gBACrC,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,gBAAgB;gBAChB,MAAM,EAAE,+CAA+C;aAC9B,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO;gBACL,IAAI,EAAE,mBAAmB;gBACzB,gBAAgB,EAAE,IAAI,CAAC,cAAc;gBACrC,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,gBAAgB;gBAChB,MAAM,EAAE,uDAAuD;aACtC,CAAC;QAC9B,CAAC;QAED,mBAAmB;QACnB,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE;YACnC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,MAAM,EAAE,GAAG,CAAC,SAAS;YACrB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,kBAAkB,EAAE,YAAY;YAChC,kBAAkB,EAAE,CAAC;SACtB,CAAC,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC;YAChC,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,gBAAgB;YAC3B,cAAc,EAAE,MAAM,CAAC,UAAU;YACjC,SAAS,EAAE,cAAc;YACzB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAC;QACH,OAAO;YACL,IAAI,EAAE,sBAAsB;YAC5B,gBAAgB,EAAE,IAAI,CAAC,cAAc;YACrC,QAAQ;SACoB,CAAC;IACjC,CAAC;IAEO,SAAS,CAAC,IAAY;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACrC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,MAAM,EAAE,CAAC,CAAC;YAChE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QACjD,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}