freshcontext-mcp 0.3.23 → 0.4.0
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.
- package/FRESHCONTEXT_SPEC.md +1 -1
- package/METHODOLOGY.md +455 -381
- package/README.md +1 -1
- package/dist/adapters/arxiv.js +1 -1
- package/dist/adapters/finance.js +1 -1
- package/dist/adapters/gdelt.js +1 -1
- package/dist/adapters/gebiz.js +1 -1
- package/dist/adapters/jobs.js +6 -6
- package/dist/adapters/reddit.js +1 -1
- package/dist/adapters/repoSearch.js +1 -1
- package/dist/adapters/secFilings.js +1 -1
- package/dist/core/decay.d.ts +3 -0
- package/dist/core/decay.js +40 -1
- package/dist/core/decision.d.ts +17 -1
- package/dist/core/decision.js +92 -11
- package/dist/core/edge.d.ts +3 -0
- package/dist/core/edge.js +18 -0
- package/dist/core/envelope.js +11 -1
- package/dist/core/index.d.ts +5 -4
- package/dist/core/index.js +3 -3
- package/dist/core/pipeline.js +10 -1
- package/dist/core/provenance.d.ts +3 -1
- package/dist/core/provenance.js +47 -0
- package/dist/core/types.d.ts +48 -0
- package/dist/rest/handler.d.ts +1 -1
- package/dist/rest/handler.js +53 -2
- package/dist/server.js +1 -1
- package/docs/CLIENT_SETUP.md +4 -4
- package/docs/CODEX_MCP_USAGE.md +4 -4
- package/docs/CORE_MCP_BOUNDARY.md +5 -5
- package/docs/FUTURE_LANES.md +1 -1
- package/docs/RELEASE_NOTES.md +129 -50
- package/package-script-guard.mjs +9 -0
- package/package.json +119 -114
- package/server.json +2 -2
package/dist/core/provenance.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
const HA_PRI_V2_VERSION = "FRESHCONTEXT_HA_PRI_V2";
|
|
3
|
+
const HA_PRI_V3_VERSION = "FRESHCONTEXT_HA_PRI_V3";
|
|
3
4
|
const NULL_SENTINEL = "null";
|
|
4
5
|
function fieldValue(value) {
|
|
5
6
|
return value ?? NULL_SENTINEL;
|
|
@@ -46,6 +47,52 @@ export function calculateHaPriV2(input) {
|
|
|
46
47
|
haPriSigV2: sha256Hex(signingPayload),
|
|
47
48
|
};
|
|
48
49
|
}
|
|
50
|
+
// Returns the canonical signing payload string only — no hash, no HMAC.
|
|
51
|
+
// The Worker reads this and signs it with Web Crypto. calculateHaPriV2
|
|
52
|
+
// additionally SHA-256-hashes the same string for the existing provenance path.
|
|
53
|
+
export function buildHaPriPayload(input) {
|
|
54
|
+
const canonicalContentSha256 = sha256Hex(canonicalizeHaPriContent(input.rawContent));
|
|
55
|
+
const semanticFingerprintSha256 = sha256Hex(fieldValue(input.semanticFingerprint));
|
|
56
|
+
const resultId = fieldValue(input.resultId);
|
|
57
|
+
const adapter = fieldValue(input.adapter);
|
|
58
|
+
const publishedAt = fieldValue(input.publishedAt);
|
|
59
|
+
const retrievedAt = fieldValue(input.retrievedAt);
|
|
60
|
+
const engineVersion = fieldValue(input.engineVersion);
|
|
61
|
+
return [
|
|
62
|
+
HA_PRI_V2_VERSION,
|
|
63
|
+
`result_id=${resultId}`,
|
|
64
|
+
`canonical_content_sha256=${canonicalContentSha256}`,
|
|
65
|
+
`semantic_fingerprint_sha256=${semanticFingerprintSha256}`,
|
|
66
|
+
`adapter=${adapter}`,
|
|
67
|
+
`published_at=${publishedAt}`,
|
|
68
|
+
`retrieved_at=${retrievedAt}`,
|
|
69
|
+
`engine_version=${engineVersion}`,
|
|
70
|
+
].join("\n");
|
|
71
|
+
}
|
|
72
|
+
// v3 payload = same 8 v2 fields + verdict_id + decision, under the V3 header.
|
|
73
|
+
// This signs the apple, not just the tree: the HMAC covers what content was seen
|
|
74
|
+
// AND what verdict was reached. Alongside v2 — does NOT replace buildHaPriPayload.
|
|
75
|
+
export function buildHaPriPayloadV3(input) {
|
|
76
|
+
const canonicalContentSha256 = sha256Hex(canonicalizeHaPriContent(input.rawContent));
|
|
77
|
+
const semanticFingerprintSha256 = sha256Hex(fieldValue(input.semanticFingerprint));
|
|
78
|
+
const resultId = fieldValue(input.resultId);
|
|
79
|
+
const adapter = fieldValue(input.adapter);
|
|
80
|
+
const publishedAt = fieldValue(input.publishedAt);
|
|
81
|
+
const retrievedAt = fieldValue(input.retrievedAt);
|
|
82
|
+
const engineVersion = fieldValue(input.engineVersion);
|
|
83
|
+
return [
|
|
84
|
+
HA_PRI_V3_VERSION,
|
|
85
|
+
`result_id=${resultId}`,
|
|
86
|
+
`canonical_content_sha256=${canonicalContentSha256}`,
|
|
87
|
+
`semantic_fingerprint_sha256=${semanticFingerprintSha256}`,
|
|
88
|
+
`adapter=${adapter}`,
|
|
89
|
+
`published_at=${publishedAt}`,
|
|
90
|
+
`retrieved_at=${retrievedAt}`,
|
|
91
|
+
`engine_version=${engineVersion}`,
|
|
92
|
+
`verdict_id=${input.verdictId}`,
|
|
93
|
+
`decision=${input.decision}`,
|
|
94
|
+
].join("\n");
|
|
95
|
+
}
|
|
49
96
|
export function verifyHaPriV2(input, actualSig) {
|
|
50
97
|
if (actualSig === null || actualSig === undefined || actualSig.trim() === "") {
|
|
51
98
|
return {
|
package/dist/core/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { StalenessVerdict } from "./decay.js";
|
|
1
2
|
export interface FreshContext {
|
|
2
3
|
content: string;
|
|
3
4
|
source_url: string;
|
|
@@ -6,6 +7,8 @@ export interface FreshContext {
|
|
|
6
7
|
freshness_confidence: "high" | "medium" | "low";
|
|
7
8
|
freshness_score: number | null;
|
|
8
9
|
adapter: string;
|
|
10
|
+
staleness: StalenessVerdict;
|
|
11
|
+
revalidate_after: string | null;
|
|
9
12
|
}
|
|
10
13
|
export interface ExtractOptions {
|
|
11
14
|
url: string;
|
|
@@ -54,9 +57,39 @@ export interface SourceProfile {
|
|
|
54
57
|
export interface ContextDecisionOptions {
|
|
55
58
|
sourceProfile?: SourceProfile | SourceProfileId;
|
|
56
59
|
intentProfile?: IntentProfileId;
|
|
60
|
+
/**
|
|
61
|
+
* Optional decision-time clock override. Controls the evaluated_at field
|
|
62
|
+
* on the returned ContextDecisionResult. Defaults to new Date() when
|
|
63
|
+
* omitted. Pass a deterministic value in tests or any caller that needs
|
|
64
|
+
* reproducible verdicts.
|
|
65
|
+
*/
|
|
66
|
+
now?: string | Date;
|
|
57
67
|
}
|
|
58
68
|
export interface ContextDecisionResult {
|
|
59
69
|
decision: ContextDecision;
|
|
70
|
+
/**
|
|
71
|
+
* Deterministic fingerprint of this verdict (signal identity + decision +
|
|
72
|
+
* profile selection). Stable across repeated evaluations of the same
|
|
73
|
+
* input; intentionally NOT derived from utility or provenance_readiness.
|
|
74
|
+
* This is the id a future verification event would reference when
|
|
75
|
+
* resolving a needs_verification (or similar) decision.
|
|
76
|
+
*/
|
|
77
|
+
verdict_id?: string;
|
|
78
|
+
/**
|
|
79
|
+
* ISO timestamp recording when this decision was computed. Always
|
|
80
|
+
* populated at runtime by the decision factory; optional in the type for
|
|
81
|
+
* backward compatibility with existing consumers that construct results
|
|
82
|
+
* manually — same convention as verdict_id. This is the stored decision-
|
|
83
|
+
* time clock — it is NOT recomputed at read time.
|
|
84
|
+
*/
|
|
85
|
+
evaluated_at?: string;
|
|
86
|
+
/**
|
|
87
|
+
* Advisory hint for when this verdict is worth re-checking, derived from
|
|
88
|
+
* the source profile's half_life_hours (evaluated_at + 1.0 × half-life).
|
|
89
|
+
* Explicit null when no source profile basis is available — never a
|
|
90
|
+
* fabricated timestamp. NOT enforcement; consumers decide what to do.
|
|
91
|
+
*/
|
|
92
|
+
revalidate_after?: string | null;
|
|
60
93
|
label: string;
|
|
61
94
|
meaning: string;
|
|
62
95
|
action: string;
|
|
@@ -159,6 +192,21 @@ export interface HaPriV2Input {
|
|
|
159
192
|
retrievedAt?: string | null;
|
|
160
193
|
engineVersion: string;
|
|
161
194
|
}
|
|
195
|
+
export interface HaPriV3Input extends HaPriV2Input {
|
|
196
|
+
/**
|
|
197
|
+
* Deterministic verdict fingerprint (SHA-256 of decision basis fields).
|
|
198
|
+
* Computed by computeVerdictId in decision.ts at evaluation time.
|
|
199
|
+
*/
|
|
200
|
+
verdictId: string;
|
|
201
|
+
/**
|
|
202
|
+
* The ContextDecision enum value (e.g., "use_first", "exclude").
|
|
203
|
+
* Typed as string so the signing layer stays free of decision-module imports.
|
|
204
|
+
* Including both verdictId and decision in the payload is intentional: the pair
|
|
205
|
+
* forms a mutual cross-check — either field tampered independently breaks the HMAC,
|
|
206
|
+
* and a verifier can read the decision without recomputing verdictId.
|
|
207
|
+
*/
|
|
208
|
+
decision: string;
|
|
209
|
+
}
|
|
162
210
|
export interface HaPriV2Material {
|
|
163
211
|
version: "FRESHCONTEXT_HA_PRI_V2";
|
|
164
212
|
resultId: string;
|
package/dist/rest/handler.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function handleRestRequest(request: Request): Promise<Response>;
|
|
1
|
+
export declare function handleRestRequest(request: Request, hmacSecret?: string): Promise<Response>;
|
package/dist/rest/handler.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { evaluateSignal, evaluateSignals } from "../core/index.js";
|
|
2
|
-
const SERVICE_VERSION = "0.
|
|
2
|
+
const SERVICE_VERSION = "0.4.0";
|
|
3
3
|
const JSON_CONTENT_TYPE = "application/json";
|
|
4
4
|
const MAX_BODY_BYTES = 256 * 1024;
|
|
5
5
|
function jsonResponse(body, status = 200) {
|
|
@@ -109,7 +109,56 @@ function handleHealth(request) {
|
|
|
109
109
|
core_available: true,
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
|
-
|
|
112
|
+
async function hmacHex(key, payload) {
|
|
113
|
+
const cryptoKey = await crypto.subtle.importKey("raw", new TextEncoder().encode(key), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
114
|
+
const buf = await crypto.subtle.sign("HMAC", cryptoKey, new TextEncoder().encode(payload));
|
|
115
|
+
return Array.from(new Uint8Array(buf))
|
|
116
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
117
|
+
.join("");
|
|
118
|
+
}
|
|
119
|
+
async function handleVerify(request, hmacSecret) {
|
|
120
|
+
if (request.method !== "POST")
|
|
121
|
+
return methodNotAllowed("POST");
|
|
122
|
+
if (!hmacSecret) {
|
|
123
|
+
return jsonResponse({
|
|
124
|
+
status: "unknown",
|
|
125
|
+
reasons: ["signing secret not configured on this host; cannot verify"],
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const parsed = await readJsonBody(request);
|
|
129
|
+
if (!parsed.ok)
|
|
130
|
+
return parsed.response;
|
|
131
|
+
const { signing_payload, signature } = parsed.body;
|
|
132
|
+
if (typeof signing_payload !== "string" || signing_payload.trim() === "") {
|
|
133
|
+
return errorResponse("invalid_request", "signing_payload must be a non-empty string.", 400);
|
|
134
|
+
}
|
|
135
|
+
// Unknown (not invalid): caller has no signature to present.
|
|
136
|
+
// Mirrors verifyHaPriV2's three-state contract: missing/empty → unknown, not invalid.
|
|
137
|
+
if (signature === undefined || signature === null) {
|
|
138
|
+
return jsonResponse({
|
|
139
|
+
status: "unknown",
|
|
140
|
+
reasons: ["signature missing or empty; verification status unknown"],
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
if (typeof signature !== "string") {
|
|
144
|
+
return errorResponse("invalid_request", "signature must be a string.", 400);
|
|
145
|
+
}
|
|
146
|
+
if (signature.trim() === "") {
|
|
147
|
+
return jsonResponse({
|
|
148
|
+
status: "unknown",
|
|
149
|
+
reasons: ["signature missing or empty; verification status unknown"],
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const expected = await hmacHex(hmacSecret, signing_payload);
|
|
153
|
+
if (signature === expected) {
|
|
154
|
+
return jsonResponse({ status: "valid", reasons: [] });
|
|
155
|
+
}
|
|
156
|
+
return jsonResponse({ status: "invalid", reasons: ["HMAC does not match recomputed signature"] });
|
|
157
|
+
}
|
|
158
|
+
// hmacSecret is injected by the Worker from env.FC_HMAC_SECRET when mounted.
|
|
159
|
+
// handler.ts never imports or holds the secret — it arrives as a call-scoped
|
|
160
|
+
// parameter. Existing callers that omit it continue to work; other routes ignore it.
|
|
161
|
+
export async function handleRestRequest(request, hmacSecret) {
|
|
113
162
|
const url = new URL(request.url);
|
|
114
163
|
try {
|
|
115
164
|
if (url.pathname === "/v1/health")
|
|
@@ -118,6 +167,8 @@ export async function handleRestRequest(request) {
|
|
|
118
167
|
return handleEvaluate(request);
|
|
119
168
|
if (url.pathname === "/v1/evaluate-batch")
|
|
120
169
|
return handleEvaluateBatch(request);
|
|
170
|
+
if (url.pathname === "/v1/verify")
|
|
171
|
+
return handleVerify(request, hmacSecret);
|
|
121
172
|
return errorResponse("not_found", `Not found: ${url.pathname}.`, 404);
|
|
122
173
|
}
|
|
123
174
|
catch {
|
package/dist/server.js
CHANGED
|
@@ -23,7 +23,7 @@ import { EvaluateContextInputError, evaluateContextInput, formatEvaluateContextR
|
|
|
23
23
|
import { formatSecurityError } from "./security.js";
|
|
24
24
|
const server = new McpServer({
|
|
25
25
|
name: "freshcontext-mcp",
|
|
26
|
-
version: "0.
|
|
26
|
+
version: "0.4.0",
|
|
27
27
|
});
|
|
28
28
|
const signalInputSchema = z.object({
|
|
29
29
|
id: z.string().optional(),
|
package/docs/CLIENT_SETUP.md
CHANGED
|
@@ -6,7 +6,7 @@ Use this guide when connecting Claude Desktop, Codex, or another MCP-compatible
|
|
|
6
6
|
|
|
7
7
|
## What You Should See
|
|
8
8
|
|
|
9
|
-
FreshContext `0.
|
|
9
|
+
FreshContext `0.4.0` exposes:
|
|
10
10
|
|
|
11
11
|
```text
|
|
12
12
|
22 tools = evaluate_context + 21 read-only reference adapters
|
|
@@ -105,8 +105,8 @@ Expected smoke result:
|
|
|
105
105
|
```json
|
|
106
106
|
{
|
|
107
107
|
"ok": true,
|
|
108
|
-
"package_version": "0.
|
|
109
|
-
"server_version": "0.
|
|
108
|
+
"package_version": "0.4.0",
|
|
109
|
+
"server_version": "0.4.0",
|
|
110
110
|
"tool_count": 22
|
|
111
111
|
}
|
|
112
112
|
```
|
|
@@ -132,7 +132,7 @@ Some clients can use `mcp-remote`:
|
|
|
132
132
|
}
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
The npm/local stdio package remains the safest default client path. The hosted Worker endpoint was last verified on 2026-06-
|
|
135
|
+
The npm/local stdio package remains the safest default client path. The hosted Worker endpoint was last verified on 2026-06-19 at `0.4.0 / 22 tools` with `evaluate_context` present and returning decision-first output, including `provenance_readiness`, `readable`, and `readable.handoff`. Because the Worker is a separate deployment surface, re-run remote verification before claiming future package interfaces are live there.
|
|
136
136
|
|
|
137
137
|
## ChatGPT / OpenAI Connector Boundary
|
|
138
138
|
|
package/docs/CODEX_MCP_USAGE.md
CHANGED
|
@@ -67,7 +67,7 @@ command = "npx"
|
|
|
67
67
|
args = ["-y", "mcp-remote", "https://freshcontext-mcp.gimmanuel73.workers.dev/mcp"]
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
This remote path was last verified on 2026-06-
|
|
70
|
+
This remote path was last verified on 2026-06-19 as a live Worker MCP endpoint exposing `0.4.0 / 22 tools`, including `evaluate_context`, `provenance_readiness`, `readable`, and `readable.handoff`. That confirms Worker availability and MCP tool discovery. It does not by itself claim Codex Cloud support or guarantee every MCP client can use the remote bridge without its own client-specific setup check.
|
|
71
71
|
|
|
72
72
|
## Verification steps
|
|
73
73
|
|
|
@@ -83,8 +83,8 @@ Expected result:
|
|
|
83
83
|
```json
|
|
84
84
|
{
|
|
85
85
|
"ok": true,
|
|
86
|
-
"package_version": "0.
|
|
87
|
-
"server_version": "0.
|
|
86
|
+
"package_version": "0.4.0",
|
|
87
|
+
"server_version": "0.4.0",
|
|
88
88
|
"tool_count": 22
|
|
89
89
|
}
|
|
90
90
|
```
|
|
@@ -102,7 +102,7 @@ Expected result: no output and exit code 0.
|
|
|
102
102
|
- Do not place secrets, credentials, registry tokens, npm tokens, GitHub tokens, or Cloudflare tokens in Codex MCP config.
|
|
103
103
|
- Do not read, edit, print, or commit local token files, local environment files, registry credentials, Cloudflare local state, or Wrangler state.
|
|
104
104
|
- Do not commit local Codex config or machine-specific paths.
|
|
105
|
-
- Prefer the local stdio path for source-checkout compatibility checks because it is verified by `npm run smoke:stdio`.
|
|
105
|
+
- Prefer the local stdio path for source-checkout compatibility checks because it is verified by `npm run smoke:stdio`.
|
|
106
106
|
- Do not claim Codex Cloud support unless it is separately tested and documented.
|
|
107
107
|
|
|
108
108
|
## Troubleshooting
|
|
@@ -50,17 +50,17 @@ Worker/site surfaces own deployment concerns:
|
|
|
50
50
|
|
|
51
51
|
Live today:
|
|
52
52
|
|
|
53
|
-
- npm package: `freshcontext-mcp@0.
|
|
53
|
+
- npm package: `freshcontext-mcp@0.4.0`
|
|
54
54
|
- MCP stdio server and published binary: `freshcontext-mcp`
|
|
55
55
|
- Core subpath export: `freshcontext-mcp/core`
|
|
56
56
|
- `evaluate_context` MCP tool for caller-provided candidate context
|
|
57
57
|
- 21 named read-only reference adapters
|
|
58
58
|
- Core signal evaluation
|
|
59
59
|
- Source Profiles
|
|
60
|
-
- Decision Helper
|
|
61
|
-
- human-readable `readable` output on structured `evaluate_context` results
|
|
62
|
-
- provenance readiness and readable handoff safety
|
|
63
|
-
- adapter registry metadata
|
|
60
|
+
- Decision Helper
|
|
61
|
+
- human-readable `readable` output on structured `evaluate_context` results
|
|
62
|
+
- provenance readiness and readable handoff safety
|
|
63
|
+
- adapter registry metadata
|
|
64
64
|
- arXiv signal-to-decision proof
|
|
65
65
|
- bring-your-own-context local demos
|
|
66
66
|
- Trust Scanner release gate
|
package/docs/FUTURE_LANES.md
CHANGED
|
@@ -10,7 +10,7 @@ The current package boundary is documented in [Core / MCP Boundary](./CORE_MCP_B
|
|
|
10
10
|
|
|
11
11
|
Live today:
|
|
12
12
|
|
|
13
|
-
- npm package: `freshcontext-mcp@0.
|
|
13
|
+
- npm package: `freshcontext-mcp@0.4.0`
|
|
14
14
|
- MCP stdio server
|
|
15
15
|
- `evaluate_context` MCP tool for caller-provided candidate context
|
|
16
16
|
- Signal Contract v1 as the stable candidate-context input shape
|
package/docs/RELEASE_NOTES.md
CHANGED
|
@@ -1,5 +1,84 @@
|
|
|
1
1
|
# FreshContext Release Notes
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
FreshContext 0.4.0 ships the signed-verdict integrity loop and the staleness envelope live in
|
|
6
|
+
production, closing the near-term arc toward context-integrity infrastructure: a judgment that
|
|
7
|
+
is not just scored, but signed, stored, verifiable, and legible as a staleness signal.
|
|
8
|
+
|
|
9
|
+
### Ha-Pri v2 / v3 Signed-Verdict Loop (live in production)
|
|
10
|
+
|
|
11
|
+
- Adds HMAC-SHA256 signing of the `evaluate_context` verdict path (v2): canonical content
|
|
12
|
+
hash, semantic fingerprint, adapter, timestamps, and version-scoped engine version, signed
|
|
13
|
+
under a server-held secret never present in Core, never logged.
|
|
14
|
+
- Adds Ha-Pri v3: extends the signed payload with `verdict_id` and the `decision` itself, so
|
|
15
|
+
the signature is tamper-evident at the verdict level. v3 runs additively alongside v2.
|
|
16
|
+
- Adds an append-only `evaluation_snapshots` ledger. Every signed verdict is stored; rows are
|
|
17
|
+
never updated or deleted. Ledger writes are non-fatal and non-blocking — a storage failure
|
|
18
|
+
can never break the caller's evaluation response.
|
|
19
|
+
- Adds a stateless `/v1/verify` endpoint: recompute-and-compare HMAC verification returning
|
|
20
|
+
`valid` / `invalid` / `unknown`, callable by any third party without holding the signing
|
|
21
|
+
secret. Verification reads the stored, version-scoped engine version, never a live constant.
|
|
22
|
+
- Live-verified in production 2026-06-30: first signed row confirmed byte-correct end to end
|
|
23
|
+
(content hash, signature, verdict_id, decision, all fields consistent across independent
|
|
24
|
+
computation paths).
|
|
25
|
+
|
|
26
|
+
### The Staleness Envelope ("the eyes")
|
|
27
|
+
|
|
28
|
+
- Adds an explicit `staleness` verdict (`fresh` / `aging` / `stale` / `unknown`) and a
|
|
29
|
+
`revalidate_after` timestamp to the FreshContext envelope (`stampFreshness` /
|
|
30
|
+
`toStructuredJSON` / `formatForLLM`), derived from the existing per-source freshness score —
|
|
31
|
+
no second decay computation, no new tunable.
|
|
32
|
+
- `revalidate_after` solves the existing exponential decay function at its "verify before
|
|
33
|
+
acting" threshold (one half-life from the content date); null when the content date is
|
|
34
|
+
unknown, in lockstep with `freshness_score`.
|
|
35
|
+
- Surfaces both the human-readable line (`Staleness: fresh (revalidate by ...)`) and the
|
|
36
|
+
structured JSON fields, so a consuming model sees staleness directly rather than having to
|
|
37
|
+
interpret a bare score.
|
|
38
|
+
- Available via the adapter/extract tools' FreshContext envelope path. Not present in
|
|
39
|
+
`evaluate_context` output, which uses a separate evaluation-result format by design.
|
|
40
|
+
- Live-verified in production 2026-07-01 via a real adapter call against the deployed Worker.
|
|
41
|
+
|
|
42
|
+
### Decay Model Validation
|
|
43
|
+
|
|
44
|
+
- Validated the per-source exponential decay model against 1,219 rows of real production data
|
|
45
|
+
across 6 active source types. Confirmed the pure freshness function is clean and correctly
|
|
46
|
+
calibrated (measured half-lives match design intent). Documented the honest scope boundary:
|
|
47
|
+
age predicts source-level decay rate, not per-item validity; per-item variance is driven by
|
|
48
|
+
content, not age alone. Full audit: `docs/FRESHCONTEXT_FLAG_A_THESIS_2026-06-30.md`.
|
|
49
|
+
|
|
50
|
+
### Methodology and Defensibility
|
|
51
|
+
|
|
52
|
+
- `METHODOLOGY.md` updated to v1.3, documenting the live signed-verdict integrity layer and
|
|
53
|
+
the decay validation, so the authored specification matches the shipped engine.
|
|
54
|
+
|
|
55
|
+
### Release Gate
|
|
56
|
+
|
|
57
|
+
- Full test suite: 344 pass / 0 fail.
|
|
58
|
+
- MCP smoke confirmed at 22 tools / 0.4.0.
|
|
59
|
+
- Trust Scanner gate: effective fail 0.
|
|
60
|
+
- Package and server metadata aligned at 0.4.0.
|
|
61
|
+
|
|
62
|
+
## 0.3.23
|
|
63
|
+
|
|
64
|
+
FreshContext 0.3.23 adds deterministic verdict identity for evaluated context results.
|
|
65
|
+
|
|
66
|
+
### Deterministic Verdict ID
|
|
67
|
+
|
|
68
|
+
- Adds `verdict_id` to structured `evaluate_context` output.
|
|
69
|
+
- `verdict_id` is deterministic: the same input signal and evaluation context always
|
|
70
|
+
produce the same identifier, enabling audit trails, caching, and downstream
|
|
71
|
+
deduplication.
|
|
72
|
+
- Keeps `verdict_id` additive: it does not change ranking, decision labels, utility
|
|
73
|
+
scoring, or existing structured output fields.
|
|
74
|
+
- Preserves full backward compatibility with 0.3.22 evaluate_context output shapes.
|
|
75
|
+
|
|
76
|
+
### Release Gate
|
|
77
|
+
|
|
78
|
+
- MCP smoke confirmed at 22 tools / 0.3.23.
|
|
79
|
+
- Trust Scanner gate: effective fail 0.
|
|
80
|
+
- Package and server metadata aligned at 0.3.23.
|
|
81
|
+
|
|
3
82
|
## 0.3.22
|
|
4
83
|
|
|
5
84
|
FreshContext 0.3.22 expands Source Profiles as judgment policies without adding adapters or retrieval behavior.
|
|
@@ -47,53 +126,53 @@ FreshContext 0.3.21 adds provenance readiness and readable handoff safety for ju
|
|
|
47
126
|
## 0.3.19
|
|
48
127
|
|
|
49
128
|
FreshContext 0.3.19 syncs the public MCP package with the new generic `evaluate_context` interface.
|
|
50
|
-
|
|
51
|
-
### Context Evaluation Front Door
|
|
52
|
-
|
|
53
|
-
- Adds `evaluate_context` as the primary MCP tool for caller-provided candidate context.
|
|
54
|
-
- Returns decision-first output for agents and users: decision, meaning, action, warnings, source, freshness, rank score, utility, confidence, and explanation.
|
|
55
|
-
- Keeps the boundary explicit: `evaluate_context` does not fetch, crawl, scrape, browse, read folders, or call adapters.
|
|
56
|
-
- Updates stdio smoke and Trust Scanner claim checks to expect 22 MCP tools: `evaluate_context` plus 21 read-only reference adapters.
|
|
57
|
-
|
|
58
|
-
### Public Framing
|
|
59
|
-
|
|
60
|
-
- Reframes the MCP package around FreshContext as context integrity infrastructure, not a 21-tool toolbox.
|
|
61
|
-
- Keeps the 21 adapter tools as read-only reference adapters and proof surfaces.
|
|
62
|
-
- Updates package-facing docs/spec language to point first at `candidate context -> FreshContext Core -> decision-ready context`.
|
|
63
|
-
|
|
64
|
-
## 0.3.18
|
|
65
|
-
|
|
66
|
-
FreshContext 0.3.18 made the MCP/Core package easier to install, validate, and explain without changing the deployed Worker runtime.
|
|
67
|
-
|
|
68
|
-
### Core and Context Evaluation
|
|
69
|
-
|
|
70
|
-
- Added the Core signal evaluation pipeline for normalized, freshness-ranked context results.
|
|
71
|
-
- Added Source Profiles as Core metadata for source-aware policy vocabulary.
|
|
72
|
-
- Added the Context Decision Helper so evaluated context can be interpreted as use, cite, verify, refresh, watch, background, or exclude.
|
|
73
|
-
- Preserved the ranking boundary: `ranked.final_score` controls default ordering, while `utility.score` remains sidecar intelligence.
|
|
74
|
-
|
|
75
|
-
### Bring Your Own Context
|
|
76
|
-
|
|
77
|
-
- Added decision-first local demos for user-provided JSON source lists.
|
|
78
|
-
- Added academic citation and jobs/opportunity sample inputs.
|
|
79
|
-
- Added `npm run demo:evaluate:file` for local source-list evaluation from a cloned source checkout.
|
|
80
|
-
|
|
81
|
-
### Adapter Path
|
|
82
|
-
|
|
83
|
-
- Added adapter registry metadata for the 21 existing MCP tools.
|
|
84
|
-
- Added additive arXiv signal extraction without changing the existing MCP `extract_arxiv` behavior.
|
|
85
|
-
- Added an arXiv signal-to-decision proof using a static fixture, Core evaluation, and decision output.
|
|
86
|
-
|
|
87
|
-
### Package and Release Hygiene
|
|
88
|
-
|
|
89
|
-
- Hardened the npm package file allowlist.
|
|
90
|
-
- Added script guards so repo-only scripts show a source-checkout notice in packed installs.
|
|
91
|
-
- Isolated Apify/Crawlee from the normal MCP npm runtime package while preserving source-checkout Apify Actor support.
|
|
92
|
-
- Confirmed fresh consumer installs no longer install Apify/Crawlee/file-type through the default MCP package path.
|
|
93
|
-
|
|
94
|
-
### Boundaries
|
|
95
|
-
|
|
96
|
-
- No Worker deploy is part of the npm package release.
|
|
97
|
-
- No hosted dashboard, billing system, Operator mode, browser crawling, or local file scanning is included.
|
|
98
|
-
- No Worker, REST handler, MCP tool schema, or existing adapter behavior changes are included in the package release itself.
|
|
99
|
-
- Future work is tracked in [`FUTURE_LANES.md`](./FUTURE_LANES.md).
|
|
129
|
+
|
|
130
|
+
### Context Evaluation Front Door
|
|
131
|
+
|
|
132
|
+
- Adds `evaluate_context` as the primary MCP tool for caller-provided candidate context.
|
|
133
|
+
- Returns decision-first output for agents and users: decision, meaning, action, warnings, source, freshness, rank score, utility, confidence, and explanation.
|
|
134
|
+
- Keeps the boundary explicit: `evaluate_context` does not fetch, crawl, scrape, browse, read folders, or call adapters.
|
|
135
|
+
- Updates stdio smoke and Trust Scanner claim checks to expect 22 MCP tools: `evaluate_context` plus 21 read-only reference adapters.
|
|
136
|
+
|
|
137
|
+
### Public Framing
|
|
138
|
+
|
|
139
|
+
- Reframes the MCP package around FreshContext as context integrity infrastructure, not a 21-tool toolbox.
|
|
140
|
+
- Keeps the 21 adapter tools as read-only reference adapters and proof surfaces.
|
|
141
|
+
- Updates package-facing docs/spec language to point first at `candidate context -> FreshContext Core -> decision-ready context`.
|
|
142
|
+
|
|
143
|
+
## 0.3.18
|
|
144
|
+
|
|
145
|
+
FreshContext 0.3.18 made the MCP/Core package easier to install, validate, and explain without changing the deployed Worker runtime.
|
|
146
|
+
|
|
147
|
+
### Core and Context Evaluation
|
|
148
|
+
|
|
149
|
+
- Added the Core signal evaluation pipeline for normalized, freshness-ranked context results.
|
|
150
|
+
- Added Source Profiles as Core metadata for source-aware policy vocabulary.
|
|
151
|
+
- Added the Context Decision Helper so evaluated context can be interpreted as use, cite, verify, refresh, watch, background, or exclude.
|
|
152
|
+
- Preserved the ranking boundary: `ranked.final_score` controls default ordering, while `utility.score` remains sidecar intelligence.
|
|
153
|
+
|
|
154
|
+
### Bring Your Own Context
|
|
155
|
+
|
|
156
|
+
- Added decision-first local demos for user-provided JSON source lists.
|
|
157
|
+
- Added academic citation and jobs/opportunity sample inputs.
|
|
158
|
+
- Added `npm run demo:evaluate:file` for local source-list evaluation from a cloned source checkout.
|
|
159
|
+
|
|
160
|
+
### Adapter Path
|
|
161
|
+
|
|
162
|
+
- Added adapter registry metadata for the 21 existing MCP tools.
|
|
163
|
+
- Added additive arXiv signal extraction without changing the existing MCP `extract_arxiv` behavior.
|
|
164
|
+
- Added an arXiv signal-to-decision proof using a static fixture, Core evaluation, and decision output.
|
|
165
|
+
|
|
166
|
+
### Package and Release Hygiene
|
|
167
|
+
|
|
168
|
+
- Hardened the npm package file allowlist.
|
|
169
|
+
- Added script guards so repo-only scripts show a source-checkout notice in packed installs.
|
|
170
|
+
- Isolated Apify/Crawlee from the normal MCP npm runtime package while preserving source-checkout Apify Actor support.
|
|
171
|
+
- Confirmed fresh consumer installs no longer install Apify/Crawlee/file-type through the default MCP package path.
|
|
172
|
+
|
|
173
|
+
### Boundaries
|
|
174
|
+
|
|
175
|
+
- No Worker deploy is part of the npm package release.
|
|
176
|
+
- No hosted dashboard, billing system, Operator mode, browser crawling, or local file scanning is included.
|
|
177
|
+
- No Worker, REST handler, MCP tool schema, or existing adapter behavior changes are included in the package release itself.
|
|
178
|
+
- Future work is tracked in [`FUTURE_LANES.md`](./FUTURE_LANES.md).
|
package/package-script-guard.mjs
CHANGED
|
@@ -106,6 +106,8 @@ const commands = {
|
|
|
106
106
|
"tests/arxivDecisionIntegration.test.ts",
|
|
107
107
|
"tests/core.test.ts",
|
|
108
108
|
"tests/haPriV2GoldenVectors.test.ts",
|
|
109
|
+
"tests/haPriV3GoldenVectors.test.ts",
|
|
110
|
+
"tests/hmacSigning.test.ts",
|
|
109
111
|
"tests/signalContractExamples.test.ts",
|
|
110
112
|
"tests/batchValidationHarness.test.ts",
|
|
111
113
|
"tests/rank.test.ts",
|
|
@@ -125,8 +127,15 @@ const commands = {
|
|
|
125
127
|
"tests/decision.test.ts",
|
|
126
128
|
"tests/evaluateContextTool.test.ts",
|
|
127
129
|
"tests/restHandler.test.ts",
|
|
130
|
+
"tests/verifyEndpoint.test.ts",
|
|
131
|
+
"tests/evaluateContextSnapshot.test.ts",
|
|
132
|
+
"tests/evaluateVerifyLoop.test.ts",
|
|
133
|
+
"tests/stalenessEnvelope.test.ts",
|
|
128
134
|
"tests/sourceProfiles.test.ts",
|
|
129
135
|
"tests/adapterRegistry.test.ts",
|
|
136
|
+
"tests/coreEdgeBoundary.test.ts",
|
|
137
|
+
"tests/lambdaSingleSource.test.ts",
|
|
138
|
+
"tests/workerDarGoldenVectors.test.ts",
|
|
130
139
|
"tests/trustScan.test.mjs",
|
|
131
140
|
],
|
|
132
141
|
},
|