|
14 | 14 | import type { Category } from "@/lib/categories"; |
15 | 15 | import type { Placement, PlacementOffer } from "@/lib/exchange"; |
16 | 16 |
|
17 | | -// --------------------------------------------------------------------------- |
18 | | -// src/lib/analyze -> analyzeSite() |
19 | | -// --------------------------------------------------------------------------- |
20 | | - |
21 | 17 | /** |
22 | | - * Everything derived from a URL at submit time. |
| 18 | + * Everything derived from a URL at submit time. Produced by `analyzeSite()` in `src/lib/analyze`. |
23 | 19 | * |
24 | 20 | * `description` must be identity-scrubbed: it is shown to potential partners |
25 | 21 | * before either side knows who the other is, so it has to say what the site |
@@ -103,12 +99,9 @@ export function analyzeFailureHint(code: AnalyzeErrorCode): string { |
103 | 99 |
|
104 | 100 | export type AnalyzeSite = (rawUrl: string) => Promise<SiteAnalysis>; |
105 | 101 |
|
106 | | -// --------------------------------------------------------------------------- |
107 | | -// src/lib/verify -> verifyLink() |
108 | | -// --------------------------------------------------------------------------- |
109 | | - |
110 | 102 | /** |
111 | | - * Result of crawling one page looking for a link to one domain. |
| 103 | + * Result of crawling one page looking for a link to one domain. Produced by `verifyLink()` in |
| 104 | + * `src/lib/verify`. |
112 | 105 | * |
113 | 106 | * POLICY REMINDER: this classifies, it does not judge. A `footer` placement or |
114 | 107 | * a `nofollow` rel is reported plainly to both parties and still counts as a |
@@ -146,11 +139,10 @@ export type VerifyLink = (input: { |
146 | 139 | detectSitewide?: boolean; |
147 | 140 | }) => Promise<LinkVerification>; |
148 | 141 |
|
149 | | -// --------------------------------------------------------------------------- |
150 | | -// src/lib/matching -> scoreCandidate() / findBestPartner() |
151 | | -// --------------------------------------------------------------------------- |
152 | | - |
153 | | -/** The subset of a site the matching engine needs. Keeps it testable without Mongo. */ |
| 142 | +/** |
| 143 | + * The subset of a site `scoreCandidate()` and `findBestPartner()` in `src/lib/matching` need. |
| 144 | + * Deliberately a plain object, so the matcher stays testable without a database. |
| 145 | + */ |
154 | 146 | export type MatchableSite = { |
155 | 147 | id: string; |
156 | 148 | ownerId: string; |
@@ -202,13 +194,12 @@ export type FindBestPartner = ( |
202 | 194 | ctx: ScoreContext, |
203 | 195 | ) => { candidate: MatchableSite; score: ScoreBreakdown } | null; |
204 | 196 |
|
205 | | -// --------------------------------------------------------------------------- |
206 | | -// Shared view models returned to MCP tools and web routes |
207 | | -// --------------------------------------------------------------------------- |
208 | | - |
209 | 197 | /** |
210 | 198 | * A site's give/get standing, counted from the links that are live right now. |
211 | 199 | * |
| 200 | + * First of the shared view models: everything from here down is returned to MCP |
| 201 | + * tools and web routes alike, which is what stops the two surfaces drifting. |
| 202 | + * |
212 | 203 | * Every view that shows these numbers takes them as a value rather than reading |
213 | 204 | * them off a site row, because they are not a property of the site: they are a |
214 | 205 | * `COUNT` over `exchange_links`, resolved by `services/standing.ts`. |
|
0 commit comments