freshcontext-mcp 0.3.20 → 0.3.21

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 (67) hide show
  1. package/README.md +55 -9
  2. package/SECURITY.md +9 -7
  3. package/dist/adapters/arxiv.d.ts +15 -0
  4. package/dist/adapters/arxiv.js +1 -1
  5. package/dist/adapters/changelog.d.ts +2 -0
  6. package/dist/adapters/finance.d.ts +2 -0
  7. package/dist/adapters/finance.js +1 -1
  8. package/dist/adapters/gdelt.d.ts +2 -0
  9. package/dist/adapters/gdelt.js +1 -1
  10. package/dist/adapters/gebiz.d.ts +2 -0
  11. package/dist/adapters/gebiz.js +1 -1
  12. package/dist/adapters/github.d.ts +2 -0
  13. package/dist/adapters/govcontracts.d.ts +2 -0
  14. package/dist/adapters/hackernews.d.ts +2 -0
  15. package/dist/adapters/jobs.d.ts +2 -0
  16. package/dist/adapters/jobs.js +6 -6
  17. package/dist/adapters/packageTrends.d.ts +2 -0
  18. package/dist/adapters/productHunt.d.ts +2 -0
  19. package/dist/adapters/reddit.d.ts +8 -0
  20. package/dist/adapters/reddit.js +1 -1
  21. package/dist/adapters/registry.d.ts +19 -0
  22. package/dist/adapters/repoSearch.d.ts +2 -0
  23. package/dist/adapters/repoSearch.js +1 -1
  24. package/dist/adapters/scholar.d.ts +2 -0
  25. package/dist/adapters/secFilings.d.ts +2 -0
  26. package/dist/adapters/secFilings.js +1 -1
  27. package/dist/adapters/yc.d.ts +2 -0
  28. package/dist/core/decay.d.ts +5 -0
  29. package/dist/core/decision.d.ts +3 -0
  30. package/dist/core/decision.js +1 -3
  31. package/dist/core/envelope.d.ts +5 -0
  32. package/dist/core/explain.d.ts +12 -0
  33. package/dist/core/guards.d.ts +1 -0
  34. package/dist/core/index.d.ts +14 -0
  35. package/dist/core/index.js +2 -0
  36. package/dist/core/pipeline.d.ts +3 -0
  37. package/dist/core/pipeline.js +8 -0
  38. package/dist/core/provenance.d.ts +5 -0
  39. package/dist/core/provenanceReadiness.d.ts +2 -0
  40. package/dist/core/provenanceReadiness.js +220 -0
  41. package/dist/core/rank.d.ts +4 -0
  42. package/dist/core/readable.d.ts +2 -0
  43. package/dist/core/readable.js +75 -0
  44. package/dist/core/signal.d.ts +3 -0
  45. package/dist/core/sourceProfiles.d.ts +4 -0
  46. package/dist/core/types.d.ts +239 -0
  47. package/dist/core/utility.d.ts +2 -0
  48. package/dist/rest/handler.d.ts +1 -0
  49. package/dist/security.d.ts +15 -0
  50. package/dist/server.d.ts +2 -0
  51. package/dist/server.js +1 -1
  52. package/dist/tools/evaluateContext.d.ts +21 -0
  53. package/dist/tools/evaluateContext.js +3 -1
  54. package/dist/tools/freshnessStamp.d.ts +1 -0
  55. package/dist/types.d.ts +1 -0
  56. package/docs/API_DESIGN.md +28 -1
  57. package/docs/CLIENT_SETUP.md +4 -4
  58. package/docs/CODEX_MCP_USAGE.md +3 -3
  59. package/docs/CORE_API.md +74 -12
  60. package/docs/CORE_MCP_BOUNDARY.md +13 -4
  61. package/docs/FUTURE_LANES.md +43 -43
  62. package/docs/HUMAN_READABLE_OUTPUT_CONTRACT.md +293 -0
  63. package/docs/RELEASE_NOTES.md +33 -5
  64. package/docs/SIGNAL_CONTRACT.md +215 -213
  65. package/package-script-guard.mjs +84 -75
  66. package/package.json +31 -16
  67. package/server.json +2 -2
package/README.md CHANGED
@@ -87,6 +87,22 @@ The production Cloudflare Worker now uses Core-backed envelope generation. Worke
87
87
 
88
88
  See [Core / MCP Boundary](./docs/CORE_MCP_BOUNDARY.md) for the current package boundary and the staged path toward a future standalone Core package.
89
89
 
90
+ ### Core import path
91
+
92
+ FreshContext Core is also available directly from the current MCP package:
93
+
94
+ ```ts
95
+ import {
96
+ evaluateSignals,
97
+ interpretEvaluations,
98
+ getSourceProfile,
99
+ normalizeSignal,
100
+ calculateHaPriV2,
101
+ } from "freshcontext-mcp/core";
102
+ ```
103
+
104
+ This is a Core subpath export inside `freshcontext-mcp`, not a standalone `freshcontext-core` package yet. The root package and `freshcontext-mcp` binary remain the MCP reference host.
105
+
90
106
  ---
91
107
 
92
108
  ## Primary MCP interface
@@ -126,9 +142,39 @@ FreshContext returns decision-first output:
126
142
  - Confidence
127
143
  - Why
128
144
 
129
- `evaluate_context` does not fetch URLs, crawl, scrape, browse, read folders, or call adapters. It only evaluates candidate context the caller provides.
130
-
131
- Current boundary: `evaluate_context` is part of the published npm/local stdio MCP server and has been verified on the hosted Cloudflare Worker MCP endpoint at `0.3.19 / 22 tools`. The Worker remains a separate deployment surface, so future package interfaces should be re-verified remotely before being claimed live.
145
+ Structured results also include a `readable` object for humans:
146
+
147
+ ```json
148
+ {
149
+ "decision": "cite_as_primary",
150
+ "label": "Cite as primary",
151
+ "readable": {
152
+ "label": "Primary source",
153
+ "summary": "This source is strong enough to use as main evidence.",
154
+ "why": [
155
+ "Strong semantic match and current freshness for arxiv.",
156
+ "source profile academic_research uses lenient date policy",
157
+ "intent profile citation_check selected"
158
+ ],
159
+ "action": "Use this as main evidence while preserving citation and provenance.",
160
+ "warnings": [
161
+ "FreshContext judges citation readiness and context usefulness; it does not certify truth."
162
+ ]
163
+ }
164
+ }
165
+ ```
166
+
167
+ The readable object translates Core decisions into user-facing language. It does not change ranking, decision labels, utility scoring, or source intake. Utility helps explain usefulness for the current question; it remains explanatory and does not control default decision labels or ranking.
168
+
169
+ FreshContext does not certify truth. It records why context was used, supported, questioned, refreshed, watched, or excluded before it reaches a model.
170
+
171
+ `evaluate_context` does not fetch URLs, crawl, scrape, browse, read folders, or call adapters. It only evaluates candidate context the caller provides.
172
+
173
+ Current boundary: `evaluate_context` is part of the npm/local stdio MCP server prepared for `0.3.21`. The hosted Cloudflare Worker MCP endpoint was last verified separately at `0.3.20 / 22 tools`. The Worker remains a separate deployment surface, so future package interfaces should be re-verified remotely before being claimed live.
174
+
175
+ ### Network Boundary
176
+
177
+ FreshContext's primary `evaluate_context` path does not fetch, crawl, scrape, browse, read folders, or call adapters. The MCP package also includes read-only reference adapters that use network access only when those adapter tools are invoked. Supply-chain scanners may therefore report package network access; that applies to the optional adapter surface, not to caller-provided context evaluation.
132
178
 
133
179
  ---
134
180
 
@@ -389,7 +435,7 @@ The reference implementation runs on Cloudflare's global edge:
389
435
  | `/` | GET | Service info + endpoint list |
390
436
  | `/health` | GET | Liveness check |
391
437
  | `/mcp` | POST | MCP JSON-RPC transport |
392
- | `/demo` | GET | Live before/after demo (no auth token required) |
438
+ | `/demo` | GET | Live before/after demo (no auth token required) |
393
439
  | `/briefing` | GET | Latest stored briefing |
394
440
  | `/v1/intel/feed/:profile_id` | GET | DAR-scored intelligence feed |
395
441
  | `/watched-queries` | GET | List all watched queries |
@@ -407,19 +453,19 @@ Production: `https://freshcontext-mcp.gimmanuel73.workers.dev`
407
453
  ## Roadmap
408
454
 
409
455
  - [x] FreshContext Specification v1.2 published (MIT, open standard)
410
- - [x] DAR engine with source-specific lambda constants (v0.3.19)
456
+ - [x] DAR engine with source-specific lambda constants
411
457
  - [x] Ha-Pri v1 provenance signatures on stored signals
412
458
  - [x] Semantic deduplication via fingerprinting
413
459
  - [x] Live before/after demo at `/demo`
414
- - [x] METHODOLOGY.md — methodology and engineering documentation
460
+ - [x] METHODOLOGY.md — methodology and engineering documentation
415
461
  - [x] Named reference adapters across intelligence, competitive research, market data, and composites
416
462
  - [x] Generic MCP `evaluate_context` tool for caller-provided candidate context
417
463
  - [x] Core-backed envelope generation shared by npm/MCP and the Cloudflare Worker
418
464
  - [x] Cloudflare Workers deployment — global edge, KV cache, KV rate limiting
419
465
  - [x] Published on npm and listed for MCP usage; Apify/feed assets are separated from the normal MCP runtime package
420
- - [x] Ha-Pri v2 Core helper and deterministic golden vectors
421
- - [x] Ha-Pri v2 production-enforcement design document
422
- - [ ] Ha-Pri v2 Worker/D1 production enforcement
466
+ - [x] Ha-Pri v2 Core helper and deterministic golden vectors
467
+ - [x] Ha-Pri v2 production-enforcement design document
468
+ - [ ] Ha-Pri v2 Worker/D1 production enforcement
423
469
  - [x] GitHub Actions release workflow — manual or `v*` tag-triggered npm publish path
424
470
  - [ ] Webhook triggers — push high-entropy signals on threshold
425
471
  - [ ] Dashboard — React frontend for the D1 intelligence pipeline
package/SECURITY.md CHANGED
@@ -25,10 +25,12 @@ For a useful report, include:
25
25
 
26
26
  Public GitHub issues are fine for non-sensitive bugs, documentation mistakes, stale claims, build failures, and feature requests.
27
27
 
28
- ## Scope Notes
29
-
30
- FreshContext does not currently offer a formal bug bounty program.
31
-
32
- Please do not send live production tokens, private Cloudflare logs, npm tokens, GitHub tokens, MCP registry tokens, customer data, or private account data. If a report requires sensitive evidence, describe the issue first by email so a safer exchange path can be agreed.
33
-
34
- This policy does not make claims of certification, compliance, guaranteed response time, or security warranty.
28
+ ## Scope Notes
29
+
30
+ FreshContext does not currently offer a formal bug bounty program.
31
+
32
+ Please do not send live production tokens, private Cloudflare logs, npm tokens, GitHub tokens, MCP registry tokens, customer data, or private account data. If a report requires sensitive evidence, describe the issue first by email so a safer exchange path can be agreed.
33
+
34
+ FreshContext's primary `evaluate_context` path evaluates caller-provided candidate context and does not fetch, crawl, browse, read folders, or call adapters. The published MCP package also includes read-only reference adapters that use network access only when those adapter tools are invoked.
35
+
36
+ This policy does not make claims of certification, compliance, guaranteed response time, or security warranty.
@@ -0,0 +1,15 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ import type { FreshContextSignalInput } from "../core/types.js";
3
+ export type ArxivSignalSearchInput = {
4
+ query: string;
5
+ maxResults?: number;
6
+ retrievedAt?: string;
7
+ semanticScore?: number;
8
+ };
9
+ /**
10
+ * arXiv adapter uses the official arXiv API.
11
+ * Accepts a search query or a direct arXiv API URL.
12
+ * Docs: https://arxiv.org/help/api/user-manual
13
+ */
14
+ export declare function arxivAdapter(options: ExtractOptions): Promise<AdapterResult>;
15
+ export declare function searchArxivSignals(input: ArxivSignalSearchInput): Promise<FreshContextSignalInput[]>;
@@ -1,5 +1,5 @@
1
1
  import { validateUrl } from "../security.js";
2
- const USER_AGENT = "freshcontext-mcp/0.1.7 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)";
2
+ const USER_AGENT = "freshcontext-mcp/0.3.21 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)";
3
3
  const DEFAULT_ARXIV_SIGNAL_SCORE = 0.8;
4
4
  function buildArxivApiUrl(input, maxResults = 10) {
5
5
  const trimmed = input.trim();
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function changelogAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function financeAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -30,7 +30,7 @@ async function fetchStooqQuote(ticker) {
30
30
  const url = `https://stooq.com/q/l/?s=${encodeURIComponent(stooqSymbol.toLowerCase())}&f=sd2t2ohlcv&h&e=json`;
31
31
  const res = await fetch(url, {
32
32
  headers: {
33
- "User-Agent": "freshcontext-mcp/0.3.19",
33
+ "User-Agent": "freshcontext-mcp/0.3.21",
34
34
  "Accept": "application/json",
35
35
  },
36
36
  });
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function gdeltAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -11,7 +11,7 @@
11
11
  */
12
12
  const HEADERS = {
13
13
  "Accept": "application/json",
14
- "User-Agent": "freshcontext-mcp/0.3.19 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)",
14
+ "User-Agent": "freshcontext-mcp/0.3.21 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)",
15
15
  };
16
16
  function parseGdeltDate(raw) {
17
17
  if (!raw)
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function gebizAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -20,7 +20,7 @@ const DATASET_ID = "d_acde1106003906a75c3fa052592f2fcb";
20
20
  const BASE_URL = "https://data.gov.sg/api/action/datastore_search";
21
21
  const HEADERS = {
22
22
  "Accept": "application/json",
23
- "User-Agent": "freshcontext-mcp/0.3.19 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)",
23
+ "User-Agent": "freshcontext-mcp/0.3.21 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)",
24
24
  };
25
25
  function formatDate(raw) {
26
26
  if (!raw)
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function githubAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function govContractsAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function hackerNewsAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function jobsAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -131,7 +131,7 @@ export async function jobsAdapter(options) {
131
131
  async function fetchRemotive(query, location, maxAgeDays, keywords) {
132
132
  const url = `https://remotive.com/api/remote-jobs?search=${encodeURIComponent(query)}&limit=15`;
133
133
  const res = await fetch(url, {
134
- headers: { "User-Agent": "freshcontext-mcp/0.3.0", "Accept": "application/json" },
134
+ headers: { "User-Agent": "freshcontext-mcp/0.3.21", "Accept": "application/json" },
135
135
  });
136
136
  if (!res.ok)
137
137
  throw new Error(`Remotive ${res.status}`);
@@ -161,7 +161,7 @@ async function fetchRemoteOK(query, location, maxAgeDays, keywords) {
161
161
  const tag = query.toLowerCase().replace(/\s+/g, "-");
162
162
  const url = `https://remoteok.com/api?tag=${encodeURIComponent(tag)}`;
163
163
  const res = await fetch(url, {
164
- headers: { "User-Agent": "freshcontext-mcp/0.3.0", "Accept": "application/json" },
164
+ headers: { "User-Agent": "freshcontext-mcp/0.3.21", "Accept": "application/json" },
165
165
  });
166
166
  if (!res.ok)
167
167
  throw new Error(`RemoteOK ${res.status}`);
@@ -199,7 +199,7 @@ async function fetchArbeitnow(query, location, maxAgeDays, keywords, remoteOnly)
199
199
  params.set("remote", "true");
200
200
  const url = `https://arbeitnow.com/api/job-board-api?${params.toString()}`;
201
201
  const res = await fetch(url, {
202
- headers: { "User-Agent": "freshcontext-mcp/0.3.0", "Accept": "application/json" },
202
+ headers: { "User-Agent": "freshcontext-mcp/0.3.21", "Accept": "application/json" },
203
203
  });
204
204
  if (!res.ok)
205
205
  throw new Error(`Arbeitnow ${res.status}`);
@@ -233,7 +233,7 @@ async function fetchMuse(query, location, maxAgeDays, keywords) {
233
233
  : "&location=Flexible%20%2F%20Remote";
234
234
  const url = `https://www.themuse.com/api/public/jobs?name=${encodeURIComponent(query)}${locParam}&page=0&descending=true`;
235
235
  const res = await fetch(url, {
236
- headers: { "User-Agent": "freshcontext-mcp/0.3.0", "Accept": "application/json" },
236
+ headers: { "User-Agent": "freshcontext-mcp/0.3.21", "Accept": "application/json" },
237
237
  });
238
238
  if (!res.ok)
239
239
  throw new Error(`The Muse ${res.status}`);
@@ -263,7 +263,7 @@ async function fetchMuse(query, location, maxAgeDays, keywords) {
263
263
  // instead of all HN comments. Uses the parent_id filter to target the thread.
264
264
  async function fetchHNHiring(query, location, maxAgeDays, keywords) {
265
265
  // Step 1: Find the most recent "Ask HN: Who is hiring?" thread
266
- const threadRes = await fetch(`https://hn.algolia.com/api/v1/search?query=Ask+HN+Who+is+hiring&tags=story&hitsPerPage=5`, { headers: { "User-Agent": "freshcontext-mcp/0.3.0" } });
266
+ const threadRes = await fetch(`https://hn.algolia.com/api/v1/search?query=Ask+HN+Who+is+hiring&tags=story&hitsPerPage=5`, { headers: { "User-Agent": "freshcontext-mcp/0.3.21" } });
267
267
  if (!threadRes.ok)
268
268
  throw new Error(`HN thread search ${threadRes.status}`);
269
269
  const threadData = await threadRes.json();
@@ -273,7 +273,7 @@ async function fetchHNHiring(query, location, maxAgeDays, keywords) {
273
273
  throw new Error("HN hiring thread not found");
274
274
  // Step 2: Search comments within that thread for the query
275
275
  const searchTerms = [query, location].filter(Boolean).join(" ");
276
- const commentsRes = await fetch(`https://hn.algolia.com/api/v1/search?query=${encodeURIComponent(searchTerms)}&tags=comment,story_${hiringThread.objectID}&hitsPerPage=10`, { headers: { "User-Agent": "freshcontext-mcp/0.3.0" } });
276
+ const commentsRes = await fetch(`https://hn.algolia.com/api/v1/search?query=${encodeURIComponent(searchTerms)}&tags=comment,story_${hiringThread.objectID}&hitsPerPage=10`, { headers: { "User-Agent": "freshcontext-mcp/0.3.21" } });
277
277
  if (!commentsRes.ok)
278
278
  throw new Error(`HN comments ${commentsRes.status}`);
279
279
  const commentsData = await commentsRes.json();
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function packageTrendsAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function productHuntAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -0,0 +1,8 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ /**
3
+ * Reddit adapter — public JSON API, no auth required.
4
+ * Accepts subreddit URLs or search queries.
5
+ * e.g. https://www.reddit.com/r/MachineLearning/.json
6
+ * https://www.reddit.com/search.json?q=mcp+server&sort=hot
7
+ */
8
+ export declare function redditAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -28,7 +28,7 @@ export async function redditAdapter(options) {
28
28
  const safeUrl = validateUrl(apiUrl, "reddit");
29
29
  const res = await fetch(safeUrl, {
30
30
  headers: {
31
- "User-Agent": "freshcontext-mcp/0.1.5 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)",
31
+ "User-Agent": "freshcontext-mcp/0.3.21 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)",
32
32
  "Accept": "application/json",
33
33
  },
34
34
  });
@@ -0,0 +1,19 @@
1
+ import type { SourceProfileId } from "../core/index.js";
2
+ export type AdapterRisk = "low" | "medium" | "high";
3
+ export type AdapterOutputMode = "single" | "batch" | "composite";
4
+ export type AdapterRuntimeKind = "api" | "browser" | "composite" | "mixed" | "local";
5
+ export interface FreshContextAdapterDescriptor {
6
+ adapter_id: string;
7
+ tool_name: string;
8
+ source_profile: SourceProfileId;
9
+ secondary_source_profiles?: SourceProfileId[];
10
+ output_mode: AdapterOutputMode;
11
+ runtime_kind: AdapterRuntimeKind;
12
+ risk: AdapterRisk;
13
+ notes?: string;
14
+ }
15
+ export declare const BUILT_IN_ADAPTER_REGISTRY: readonly FreshContextAdapterDescriptor[];
16
+ export declare function listAdapterDescriptors(): FreshContextAdapterDescriptor[];
17
+ export declare function getAdapterDescriptor(adapterIdOrToolName: string): FreshContextAdapterDescriptor | undefined;
18
+ export declare function listAdaptersBySourceProfile(profileId: SourceProfileId): FreshContextAdapterDescriptor[];
19
+ export declare function listAdaptersByRisk(risk: AdapterRisk): FreshContextAdapterDescriptor[];
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function repoSearchAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -22,7 +22,7 @@ export async function repoSearchAdapter(options) {
22
22
  const res = await fetch(apiUrl, {
23
23
  headers: {
24
24
  Accept: "application/vnd.github.v3+json",
25
- "User-Agent": "freshcontext-mcp/0.3.19 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)",
25
+ "User-Agent": "freshcontext-mcp/0.3.21 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)",
26
26
  },
27
27
  });
28
28
  if (!res.ok) {
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function scholarAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function secFilingsAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -12,7 +12,7 @@
12
12
  */
13
13
  const HEADERS = {
14
14
  "Accept": "application/json",
15
- "User-Agent": "freshcontext-mcp/0.3.19 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)",
15
+ "User-Agent": "freshcontext-mcp/0.3.21 (https://github.com/PrinceGabriel-lgtm/freshcontext-mcp)",
16
16
  };
17
17
  async function fetchSecFilings(query, maxResults = 10) {
18
18
  const today = new Date().toISOString().slice(0, 10);
@@ -0,0 +1,2 @@
1
+ import { AdapterResult, ExtractOptions } from "../types.js";
2
+ export declare function ycAdapter(options: ExtractOptions): Promise<AdapterResult>;
@@ -0,0 +1,5 @@
1
+ export declare const LAMBDA: Record<string, number>;
2
+ export declare const FUTURE_CLOCK_SKEW_TOLERANCE_MS: number;
3
+ export declare function isMeaningfullyFutureDate(content_date: string | null, retrieved_at: string): boolean;
4
+ export declare function calculateFreshnessScore(content_date: string | null, retrieved_at: string, adapter: string): number | null;
5
+ export declare function scoreLabel(score: number | null): string;
@@ -0,0 +1,3 @@
1
+ import type { ContextDecisionOptions, ContextDecisionResult, CoreSignalEvaluationResult } from "./types.js";
2
+ export declare function interpretEvaluation(evaluation: CoreSignalEvaluationResult, options?: ContextDecisionOptions): ContextDecisionResult;
3
+ export declare function interpretEvaluations(evaluations: CoreSignalEvaluationResult[], options?: ContextDecisionOptions): ContextDecisionResult[];
@@ -125,7 +125,6 @@ export function interpretEvaluation(evaluation, options = {}) {
125
125
  ]);
126
126
  const warnings = [...nonAdviceWarnings(intentProfile)];
127
127
  const finalScore = evaluation.ranked.final_score;
128
- const utilityScore = evaluation.utility.score;
129
128
  const freshnessScore = evaluation.freshness_score;
130
129
  const confidence = evaluation.ranked.confidence;
131
130
  const isFailed = evaluation.signal.status === "failed"
@@ -153,7 +152,6 @@ export function interpretEvaluation(evaluation, options = {}) {
153
152
  if (finalScore >= 0.85
154
153
  && freshnessScore !== null
155
154
  && freshnessScore >= 70
156
- && utilityScore >= 60
157
155
  && confidence === "high") {
158
156
  if (sourceProfile?.authority_hint === "high" && isCitationIntent(intentProfile)) {
159
157
  return decisionResult("cite_as_primary", reasons, warnings);
@@ -163,7 +161,7 @@ export function interpretEvaluation(evaluation, options = {}) {
163
161
  if (finalScore >= 0.55 && freshnessScore !== null && freshnessScore < 50) {
164
162
  return decisionResult(isCitationIntent(intentProfile) ? "cite_as_supporting" : "use_as_background", reasons, warnings);
165
163
  }
166
- if (finalScore < 0.35 && utilityScore < 30) {
164
+ if (finalScore < 0.35) {
167
165
  return decisionResult(confidence === "low" ? "exclude" : "watch_only", reasons, warnings);
168
166
  }
169
167
  if (finalScore >= 0.55) {
@@ -0,0 +1,5 @@
1
+ import type { FreshContext, AdapterResult, ExtractOptions, EnvelopeFormatOptions } from "./types.js";
2
+ export declare const MAX_ENVELOPE_CONTENT_LENGTH = 20000;
3
+ export declare function stampFreshness(result: AdapterResult, options: ExtractOptions, adapter: string): FreshContext;
4
+ export declare function toStructuredJSON(ctx: FreshContext): object;
5
+ export declare function formatForLLM(ctx: FreshContext, options?: EnvelopeFormatOptions): string;
@@ -0,0 +1,12 @@
1
+ import type { SignalConfidence } from "./types.js";
2
+ interface ExplainSignalInput {
3
+ source?: string;
4
+ source_type?: string;
5
+ semantic_score: number;
6
+ freshness_score: number | null;
7
+ final_score: number;
8
+ confidence: SignalConfidence;
9
+ published_at?: string | null;
10
+ }
11
+ export declare function explainSignal(input: ExplainSignalInput): string;
12
+ export {};
@@ -0,0 +1 @@
1
+ export declare function looksLikeFailedAdapterContent(raw: string): boolean;
@@ -0,0 +1,14 @@
1
+ export { LAMBDA, calculateFreshnessScore, scoreLabel } from "./decay.js";
2
+ export { looksLikeFailedAdapterContent } from "./guards.js";
3
+ export { stampFreshness, toStructuredJSON, formatForLLM } from "./envelope.js";
4
+ export { explainSignal } from "./explain.js";
5
+ export { rankSignals, rankSignal, clampScore } from "./rank.js";
6
+ export { calculateContextUtility } from "./utility.js";
7
+ export { SIGNAL_CONTRACT_VERSION, normalizeSignal } from "./signal.js";
8
+ export { evaluateSignal, evaluateSignals } from "./pipeline.js";
9
+ export { interpretEvaluation, interpretEvaluations } from "./decision.js";
10
+ export { toReadableContextResult } from "./readable.js";
11
+ export { prepareProvenanceReadiness } from "./provenanceReadiness.js";
12
+ export { BUILT_IN_SOURCE_PROFILES, getSourceProfile, listSourceProfiles } from "./sourceProfiles.js";
13
+ export { canonicalizeHaPriContent, sha256Hex, calculateHaPriV2, verifyHaPriV2, } from "./provenance.js";
14
+ export type { FreshContext, ExtractOptions, AdapterResult, EnvelopeFormatOptions, SignalConfidence, SignalDateConfidence, SignalContractVersion, SourceAuthorityHint, SourceDatePolicy, SourceFailurePolicy, SourceProfile, SourceProfileId, SourceSurface, ContextDecision, IntentProfileId, ContextDecisionOptions, ContextDecisionResult, HumanReadableHandoffResult, HumanReadableContextResult, SignalNormalizeOptions, FreshContextSignalInput, FreshContextSignal, FreshSignal, RankedSignal, RankOptions, ContextUtilityStatus, ContextUtilityInput, ContextUtilityResult, HaPriV2Input, HaPriV2Material, HaPriV2Result, HaPriVerificationStatus, HaPriV2VerificationResult, ProvenanceReadinessState, ProvenanceSourceIdentityCompleteness, ProvenanceTimingCompleteness, ProvenanceReadinessInput, ProvenanceReadinessOptions, ProvenanceSourceIdentityResult, ProvenanceReadinessResult, CoreSignalProvenanceOptions, CoreSignalEnvelopeResult, CoreSignalEvaluationOptions, CoreSignalEvaluationResult, } from "./types.js";
@@ -7,5 +7,7 @@ export { calculateContextUtility } from "./utility.js";
7
7
  export { SIGNAL_CONTRACT_VERSION, normalizeSignal } from "./signal.js";
8
8
  export { evaluateSignal, evaluateSignals } from "./pipeline.js";
9
9
  export { interpretEvaluation, interpretEvaluations } from "./decision.js";
10
+ export { toReadableContextResult } from "./readable.js";
11
+ export { prepareProvenanceReadiness } from "./provenanceReadiness.js";
10
12
  export { BUILT_IN_SOURCE_PROFILES, getSourceProfile, listSourceProfiles } from "./sourceProfiles.js";
11
13
  export { canonicalizeHaPriContent, sha256Hex, calculateHaPriV2, verifyHaPriV2, } from "./provenance.js";
@@ -0,0 +1,3 @@
1
+ import type { CoreSignalEvaluationOptions, CoreSignalEvaluationResult, FreshContextSignalInput } from "./types.js";
2
+ export declare function evaluateSignal(input: FreshContextSignalInput, options?: CoreSignalEvaluationOptions): CoreSignalEvaluationResult;
3
+ export declare function evaluateSignals(inputs: FreshContextSignalInput[], options?: CoreSignalEvaluationOptions): CoreSignalEvaluationResult[];
@@ -1,6 +1,7 @@
1
1
  import { LAMBDA, calculateFreshnessScore } from "./decay.js";
2
2
  import { formatForLLM, toStructuredJSON } from "./envelope.js";
3
3
  import { calculateHaPriV2 } from "./provenance.js";
4
+ import { prepareProvenanceReadiness } from "./provenanceReadiness.js";
4
5
  import { rankSignal } from "./rank.js";
5
6
  import { normalizeSignal } from "./signal.js";
6
7
  import { calculateContextUtility } from "./utility.js";
@@ -79,6 +80,12 @@ export function evaluateSignal(input, options = {}) {
79
80
  const reasons = [...signal.reasons, ...utility.reasons];
80
81
  const envelope = createEnvelope(signal, freshness_score, options);
81
82
  const provenance = createProvenance(signal, options, reasons);
83
+ const provenance_readiness = prepareProvenanceReadiness(signal, {
84
+ now: options.now,
85
+ resultId: options.provenance?.resultId ?? signal.id,
86
+ semanticFingerprint: options.provenance?.semanticFingerprint ?? null,
87
+ engineVersion: options.provenance?.engineVersion,
88
+ });
82
89
  return {
83
90
  signal,
84
91
  freshness_score,
@@ -87,6 +94,7 @@ export function evaluateSignal(input, options = {}) {
87
94
  explanation: ranked.reason,
88
95
  envelope,
89
96
  provenance,
97
+ provenance_readiness,
90
98
  reasons,
91
99
  };
92
100
  }
@@ -0,0 +1,5 @@
1
+ import type { HaPriV2Input, HaPriV2Result, HaPriV2VerificationResult } from "./types.js";
2
+ export declare function canonicalizeHaPriContent(input: string): string;
3
+ export declare function sha256Hex(input: string): string;
4
+ export declare function calculateHaPriV2(input: HaPriV2Input): HaPriV2Result;
5
+ export declare function verifyHaPriV2(input: HaPriV2Input, actualSig: string | null | undefined): HaPriV2VerificationResult;
@@ -0,0 +1,2 @@
1
+ import type { ProvenanceReadinessInput, ProvenanceReadinessOptions, ProvenanceReadinessResult } from "./types.js";
2
+ export declare function prepareProvenanceReadiness(input: ProvenanceReadinessInput, options?: ProvenanceReadinessOptions): ProvenanceReadinessResult;