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.
- package/README.md +55 -9
- package/SECURITY.md +9 -7
- package/dist/adapters/arxiv.d.ts +15 -0
- package/dist/adapters/arxiv.js +1 -1
- package/dist/adapters/changelog.d.ts +2 -0
- package/dist/adapters/finance.d.ts +2 -0
- package/dist/adapters/finance.js +1 -1
- package/dist/adapters/gdelt.d.ts +2 -0
- package/dist/adapters/gdelt.js +1 -1
- package/dist/adapters/gebiz.d.ts +2 -0
- package/dist/adapters/gebiz.js +1 -1
- package/dist/adapters/github.d.ts +2 -0
- package/dist/adapters/govcontracts.d.ts +2 -0
- package/dist/adapters/hackernews.d.ts +2 -0
- package/dist/adapters/jobs.d.ts +2 -0
- package/dist/adapters/jobs.js +6 -6
- package/dist/adapters/packageTrends.d.ts +2 -0
- package/dist/adapters/productHunt.d.ts +2 -0
- package/dist/adapters/reddit.d.ts +8 -0
- package/dist/adapters/reddit.js +1 -1
- package/dist/adapters/registry.d.ts +19 -0
- package/dist/adapters/repoSearch.d.ts +2 -0
- package/dist/adapters/repoSearch.js +1 -1
- package/dist/adapters/scholar.d.ts +2 -0
- package/dist/adapters/secFilings.d.ts +2 -0
- package/dist/adapters/secFilings.js +1 -1
- package/dist/adapters/yc.d.ts +2 -0
- package/dist/core/decay.d.ts +5 -0
- package/dist/core/decision.d.ts +3 -0
- package/dist/core/decision.js +1 -3
- package/dist/core/envelope.d.ts +5 -0
- package/dist/core/explain.d.ts +12 -0
- package/dist/core/guards.d.ts +1 -0
- package/dist/core/index.d.ts +14 -0
- package/dist/core/index.js +2 -0
- package/dist/core/pipeline.d.ts +3 -0
- package/dist/core/pipeline.js +8 -0
- package/dist/core/provenance.d.ts +5 -0
- package/dist/core/provenanceReadiness.d.ts +2 -0
- package/dist/core/provenanceReadiness.js +220 -0
- package/dist/core/rank.d.ts +4 -0
- package/dist/core/readable.d.ts +2 -0
- package/dist/core/readable.js +75 -0
- package/dist/core/signal.d.ts +3 -0
- package/dist/core/sourceProfiles.d.ts +4 -0
- package/dist/core/types.d.ts +239 -0
- package/dist/core/utility.d.ts +2 -0
- package/dist/rest/handler.d.ts +1 -0
- package/dist/security.d.ts +15 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +1 -1
- package/dist/tools/evaluateContext.d.ts +21 -0
- package/dist/tools/evaluateContext.js +3 -1
- package/dist/tools/freshnessStamp.d.ts +1 -0
- package/dist/types.d.ts +1 -0
- package/docs/API_DESIGN.md +28 -1
- package/docs/CLIENT_SETUP.md +4 -4
- package/docs/CODEX_MCP_USAGE.md +3 -3
- package/docs/CORE_API.md +74 -12
- package/docs/CORE_MCP_BOUNDARY.md +13 -4
- package/docs/FUTURE_LANES.md +43 -43
- package/docs/HUMAN_READABLE_OUTPUT_CONTRACT.md +293 -0
- package/docs/RELEASE_NOTES.md +33 -5
- package/docs/SIGNAL_CONTRACT.md +215 -213
- package/package-script-guard.mjs +84 -75
- package/package.json +31 -16
- package/server.json +2 -2
package/docs/SIGNAL_CONTRACT.md
CHANGED
|
@@ -1,30 +1,32 @@
|
|
|
1
|
-
# FreshContext Signal Contract v1
|
|
2
|
-
|
|
3
|
-
FreshContext Signal Contract v1 is the current FreshContext input standard: the stable shape for candidate context that should be judged before it reaches a model.
|
|
4
|
-
|
|
5
|
-
In plain terms:
|
|
6
|
-
|
|
7
|
-
```text
|
|
8
|
-
candidate context -> Signal Contract v1 -> FreshContext judgment -> decision-ready context
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
The Signal Contract is live product architecture. It is used by Core normalization, `evaluate_context`, bring-your-own-context demos, reference adapter signal paths, and future batch validation.
|
|
12
|
-
|
|
13
|
-
Do not rename this with future-signal terminology. Future context signals, control signals, provenance confidence signals, and richer decision metadata are optional future layers on top of this stable input shape. They are not replacements for Signal Contract v1 and are not required fields today.
|
|
14
|
-
|
|
15
|
-
It is an additive Core API. It does not change MCP tool schemas, Worker runtime behavior, D1 schema, Store scoring, feeds, or deployment behavior.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
1
|
+
# FreshContext Signal Contract v1
|
|
2
|
+
|
|
3
|
+
FreshContext Signal Contract v1 is the current FreshContext input standard: the stable shape for candidate context that should be judged before it reaches a model.
|
|
4
|
+
|
|
5
|
+
In plain terms:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
candidate context -> Signal Contract v1 -> FreshContext judgment -> decision-ready context
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The Signal Contract is live product architecture. It is used by Core normalization, `evaluate_context`, bring-your-own-context demos, reference adapter signal paths, and future batch validation.
|
|
12
|
+
|
|
13
|
+
Do not rename this with future-signal terminology. Future context signals, control signals, provenance confidence signals, and richer decision metadata are optional future layers on top of this stable input shape. They are not replacements for Signal Contract v1 and are not required fields today.
|
|
14
|
+
|
|
15
|
+
It is an additive Core API. It does not change MCP tool schemas, Worker runtime behavior, D1 schema, Store scoring, feeds, or deployment behavior.
|
|
16
|
+
|
|
17
|
+
Provenance readiness is an output-side judgment over this signal material. It can warn about weak source identity or missing timing metadata without adding new required input fields.
|
|
18
|
+
|
|
19
|
+
## Batch Validation Harness
|
|
20
|
+
|
|
21
|
+
Source checkouts include a small validation harness for testing larger Signal Contract v1 batches:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm run batch:validate -- examples/batches/signal-contract-v1.academic.json
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The harness reads caller-provided JSON, evaluates it through Core, summarizes status/date/decision counts, and prints a structured evidence block. It does not add required fields to the Signal Contract and does not fetch, crawl, scan folders, or call reference adapters.
|
|
28
|
+
|
|
29
|
+
Replay output includes concise decision explanations and small reason-code lists for top results and human-review mismatches. These are reporting aids for auditability: they surface whether relevance, freshness, date confidence, status, utility, score normalization, or Source Profile behavior influenced a treatment label. They do not change Core scoring, ranking, normalization, or decision thresholds, and they do not certify truth.
|
|
28
30
|
|
|
29
31
|
## Contract Version
|
|
30
32
|
|
|
@@ -38,9 +40,9 @@ Every normalized signal includes:
|
|
|
38
40
|
contract_version: "freshcontext.signal.v1"
|
|
39
41
|
```
|
|
40
42
|
|
|
41
|
-
## Input Shape
|
|
42
|
-
|
|
43
|
-
`FreshContextSignalInput` accepts the common fields used by adapters, agents, ranking, `evaluate_context`, and future Store wiring:
|
|
43
|
+
## Input Shape
|
|
44
|
+
|
|
45
|
+
`FreshContextSignalInput` accepts the common fields used by adapters, agents, ranking, `evaluate_context`, and future Store wiring:
|
|
44
46
|
|
|
45
47
|
```ts
|
|
46
48
|
interface FreshContextSignalInput {
|
|
@@ -60,21 +62,21 @@ interface FreshContextSignalInput {
|
|
|
60
62
|
}
|
|
61
63
|
```
|
|
62
64
|
|
|
63
|
-
`published_at` is the canonical signal timestamp. `content_date` is accepted as an adapter/envelope compatibility alias.
|
|
64
|
-
|
|
65
|
-
Minimal caller-provided input usually looks like:
|
|
66
|
-
|
|
67
|
-
```json
|
|
68
|
-
{
|
|
69
|
-
"title": "Example source",
|
|
70
|
-
"content": "Candidate context text...",
|
|
71
|
-
"source": "https://example.com/source",
|
|
72
|
-
"source_type": "official_docs",
|
|
73
|
-
"published_at": "2026-06-01T00:00:00.000Z",
|
|
74
|
-
"retrieved_at": "2026-06-09T00:00:00.000Z",
|
|
75
|
-
"semantic_score": 0.92
|
|
76
|
-
}
|
|
77
|
-
```
|
|
65
|
+
`published_at` is the canonical signal timestamp. `content_date` is accepted as an adapter/envelope compatibility alias.
|
|
66
|
+
|
|
67
|
+
Minimal caller-provided input usually looks like:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"title": "Example source",
|
|
72
|
+
"content": "Candidate context text...",
|
|
73
|
+
"source": "https://example.com/source",
|
|
74
|
+
"source_type": "official_docs",
|
|
75
|
+
"published_at": "2026-06-01T00:00:00.000Z",
|
|
76
|
+
"retrieved_at": "2026-06-09T00:00:00.000Z",
|
|
77
|
+
"semantic_score": 0.92
|
|
78
|
+
}
|
|
79
|
+
```
|
|
78
80
|
|
|
79
81
|
## Normalized Output
|
|
80
82
|
|
|
@@ -98,166 +100,166 @@ interface FreshContextSignal {
|
|
|
98
100
|
}
|
|
99
101
|
```
|
|
100
102
|
|
|
101
|
-
## Normalization Rules
|
|
102
|
-
|
|
103
|
-
- Missing or invalid `published_at` / `content_date` becomes `published_at: null`.
|
|
103
|
+
## Normalization Rules
|
|
104
|
+
|
|
105
|
+
- Missing or invalid `published_at` / `content_date` becomes `published_at: null`.
|
|
104
106
|
- `content_date` maps to `published_at` when `published_at` is absent.
|
|
105
107
|
- Meaningfully future-dated timestamps are cleared and receive `date_confidence: "unknown"`.
|
|
106
108
|
- Small clock skew is tolerated by the same Core freshness policy used by envelope scoring.
|
|
107
109
|
- Failed, empty, timeout, blocked, or error-looking content becomes `status: "failed"`.
|
|
108
110
|
- Missing, invalid, negative, or oversized `semantic_score` is clamped into `0..1`.
|
|
109
|
-
- `metadata` is shallow-copied so normalization does not mutate caller-owned objects.
|
|
110
|
-
- `reasons` records meaningful normalization changes.
|
|
111
|
-
|
|
112
|
-
## Examples
|
|
113
|
-
|
|
114
|
-
These examples are intentionally small. They show the current contract shape, not future optional metadata.
|
|
115
|
-
|
|
116
|
-
### Valid Candidate Signals
|
|
117
|
-
|
|
118
|
-
Academic research:
|
|
119
|
-
|
|
120
|
-
```json
|
|
121
|
-
{
|
|
122
|
-
"title": "A fresh retrieval-augmented generation benchmark",
|
|
123
|
-
"content": "The paper reports a 2026 benchmark for retrieval-augmented generation systems.",
|
|
124
|
-
"source": "https://arxiv.org/abs/2606.00001",
|
|
125
|
-
"source_type": "arxiv",
|
|
126
|
-
"published_at": "2026-06-01T09:00:00.000Z",
|
|
127
|
-
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
128
|
-
"semantic_score": 0.94,
|
|
129
|
-
"metadata": {
|
|
130
|
-
"profile": "academic_research"
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
Official docs:
|
|
136
|
-
|
|
137
|
-
```json
|
|
138
|
-
{
|
|
139
|
-
"title": "API changelog",
|
|
140
|
-
"content": "The official changelog documents the current API behavior.",
|
|
141
|
-
"source": "https://docs.example.com/changelog",
|
|
142
|
-
"source_type": "official_docs",
|
|
143
|
-
"published_at": "2026-06-08T10:00:00.000Z",
|
|
144
|
-
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
145
|
-
"semantic_score": 0.88
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Jobs/opportunities:
|
|
150
|
-
|
|
151
|
-
```json
|
|
152
|
-
{
|
|
153
|
-
"title": "AI tools engineer",
|
|
154
|
-
"content": "A current remote role for an AI tools engineer.",
|
|
155
|
-
"source": "https://jobs.example.com/ai-tools-engineer",
|
|
156
|
-
"source_type": "jobs",
|
|
157
|
-
"published_at": "2026-06-07T08:00:00.000Z",
|
|
158
|
-
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
159
|
-
"semantic_score": 0.86
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Market/finance:
|
|
164
|
-
|
|
165
|
-
```json
|
|
166
|
-
{
|
|
167
|
-
"title": "Company quarterly update",
|
|
168
|
-
"content": "The company reported current quarter revenue and guidance.",
|
|
169
|
-
"source": "https://investors.example.com/q2-update",
|
|
170
|
-
"source_type": "finance",
|
|
171
|
-
"published_at": "2026-06-09T07:00:00.000Z",
|
|
172
|
-
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
173
|
-
"semantic_score": 0.83
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Social pulse:
|
|
178
|
-
|
|
179
|
-
```json
|
|
180
|
-
{
|
|
181
|
-
"title": "Developer discussion",
|
|
182
|
-
"content": "Developers are discussing setup friction and recent adoption.",
|
|
183
|
-
"source": "https://news.ycombinator.com/item?id=123456",
|
|
184
|
-
"source_type": "hackernews",
|
|
185
|
-
"published_at": "2026-06-09T11:00:00.000Z",
|
|
186
|
-
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
187
|
-
"semantic_score": 0.71
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### Invalid Or Risky Candidate Signals
|
|
192
|
-
|
|
193
|
-
Missing date:
|
|
194
|
-
|
|
195
|
-
```json
|
|
196
|
-
{
|
|
197
|
-
"title": "Relevant source with no date",
|
|
198
|
-
"content": "Useful candidate context, but no publication timestamp is available.",
|
|
199
|
-
"source": "https://example.com/no-date",
|
|
200
|
-
"source_type": "official_docs",
|
|
201
|
-
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
202
|
-
"semantic_score": 0.78
|
|
203
|
-
}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
Invalid timestamp:
|
|
207
|
-
|
|
208
|
-
```json
|
|
209
|
-
{
|
|
210
|
-
"title": "Invalid date source",
|
|
211
|
-
"content": "Candidate context with malformed date metadata.",
|
|
212
|
-
"source": "https://example.com/bad-date",
|
|
213
|
-
"source_type": "official_docs",
|
|
214
|
-
"published_at": "not-a-date",
|
|
215
|
-
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
216
|
-
"semantic_score": 0.78
|
|
217
|
-
}
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
Meaningfully future-dated timestamp:
|
|
221
|
-
|
|
222
|
-
```json
|
|
223
|
-
{
|
|
224
|
-
"title": "Future-dated source",
|
|
225
|
-
"content": "Candidate context whose publication timestamp is after retrieval time.",
|
|
226
|
-
"source": "https://example.com/future-date",
|
|
227
|
-
"source_type": "official_docs",
|
|
228
|
-
"published_at": "2026-06-09T12:06:00.000Z",
|
|
229
|
-
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
230
|
-
"semantic_score": 0.78
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
Failed/error-looking content:
|
|
235
|
-
|
|
236
|
-
```json
|
|
237
|
-
{
|
|
238
|
-
"title": "Blocked source",
|
|
239
|
-
"content": "[Error] upstream timeout",
|
|
240
|
-
"source": "https://example.com/blocked",
|
|
241
|
-
"source_type": "official_docs",
|
|
242
|
-
"published_at": "2026-06-09T10:00:00.000Z",
|
|
243
|
-
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
244
|
-
"semantic_score": 0.91
|
|
245
|
-
}
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
Out-of-range semantic score:
|
|
249
|
-
|
|
250
|
-
```json
|
|
251
|
-
{
|
|
252
|
-
"title": "Overscored source",
|
|
253
|
-
"content": "Candidate context with an out-of-range relevance score.",
|
|
254
|
-
"source": "https://example.com/overscored",
|
|
255
|
-
"source_type": "official_docs",
|
|
256
|
-
"published_at": "2026-06-09T10:00:00.000Z",
|
|
257
|
-
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
258
|
-
"semantic_score": 1.7
|
|
259
|
-
}
|
|
260
|
-
```
|
|
111
|
+
- `metadata` is shallow-copied so normalization does not mutate caller-owned objects.
|
|
112
|
+
- `reasons` records meaningful normalization changes.
|
|
113
|
+
|
|
114
|
+
## Examples
|
|
115
|
+
|
|
116
|
+
These examples are intentionally small. They show the current contract shape, not future optional metadata.
|
|
117
|
+
|
|
118
|
+
### Valid Candidate Signals
|
|
119
|
+
|
|
120
|
+
Academic research:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"title": "A fresh retrieval-augmented generation benchmark",
|
|
125
|
+
"content": "The paper reports a 2026 benchmark for retrieval-augmented generation systems.",
|
|
126
|
+
"source": "https://arxiv.org/abs/2606.00001",
|
|
127
|
+
"source_type": "arxiv",
|
|
128
|
+
"published_at": "2026-06-01T09:00:00.000Z",
|
|
129
|
+
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
130
|
+
"semantic_score": 0.94,
|
|
131
|
+
"metadata": {
|
|
132
|
+
"profile": "academic_research"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Official docs:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"title": "API changelog",
|
|
142
|
+
"content": "The official changelog documents the current API behavior.",
|
|
143
|
+
"source": "https://docs.example.com/changelog",
|
|
144
|
+
"source_type": "official_docs",
|
|
145
|
+
"published_at": "2026-06-08T10:00:00.000Z",
|
|
146
|
+
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
147
|
+
"semantic_score": 0.88
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Jobs/opportunities:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"title": "AI tools engineer",
|
|
156
|
+
"content": "A current remote role for an AI tools engineer.",
|
|
157
|
+
"source": "https://jobs.example.com/ai-tools-engineer",
|
|
158
|
+
"source_type": "jobs",
|
|
159
|
+
"published_at": "2026-06-07T08:00:00.000Z",
|
|
160
|
+
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
161
|
+
"semantic_score": 0.86
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Market/finance:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"title": "Company quarterly update",
|
|
170
|
+
"content": "The company reported current quarter revenue and guidance.",
|
|
171
|
+
"source": "https://investors.example.com/q2-update",
|
|
172
|
+
"source_type": "finance",
|
|
173
|
+
"published_at": "2026-06-09T07:00:00.000Z",
|
|
174
|
+
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
175
|
+
"semantic_score": 0.83
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Social pulse:
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"title": "Developer discussion",
|
|
184
|
+
"content": "Developers are discussing setup friction and recent adoption.",
|
|
185
|
+
"source": "https://news.ycombinator.com/item?id=123456",
|
|
186
|
+
"source_type": "hackernews",
|
|
187
|
+
"published_at": "2026-06-09T11:00:00.000Z",
|
|
188
|
+
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
189
|
+
"semantic_score": 0.71
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Invalid Or Risky Candidate Signals
|
|
194
|
+
|
|
195
|
+
Missing date:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"title": "Relevant source with no date",
|
|
200
|
+
"content": "Useful candidate context, but no publication timestamp is available.",
|
|
201
|
+
"source": "https://example.com/no-date",
|
|
202
|
+
"source_type": "official_docs",
|
|
203
|
+
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
204
|
+
"semantic_score": 0.78
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Invalid timestamp:
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"title": "Invalid date source",
|
|
213
|
+
"content": "Candidate context with malformed date metadata.",
|
|
214
|
+
"source": "https://example.com/bad-date",
|
|
215
|
+
"source_type": "official_docs",
|
|
216
|
+
"published_at": "not-a-date",
|
|
217
|
+
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
218
|
+
"semantic_score": 0.78
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Meaningfully future-dated timestamp:
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"title": "Future-dated source",
|
|
227
|
+
"content": "Candidate context whose publication timestamp is after retrieval time.",
|
|
228
|
+
"source": "https://example.com/future-date",
|
|
229
|
+
"source_type": "official_docs",
|
|
230
|
+
"published_at": "2026-06-09T12:06:00.000Z",
|
|
231
|
+
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
232
|
+
"semantic_score": 0.78
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Failed/error-looking content:
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"title": "Blocked source",
|
|
241
|
+
"content": "[Error] upstream timeout",
|
|
242
|
+
"source": "https://example.com/blocked",
|
|
243
|
+
"source_type": "official_docs",
|
|
244
|
+
"published_at": "2026-06-09T10:00:00.000Z",
|
|
245
|
+
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
246
|
+
"semantic_score": 0.91
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Out-of-range semantic score:
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
{
|
|
254
|
+
"title": "Overscored source",
|
|
255
|
+
"content": "Candidate context with an out-of-range relevance score.",
|
|
256
|
+
"source": "https://example.com/overscored",
|
|
257
|
+
"source_type": "official_docs",
|
|
258
|
+
"published_at": "2026-06-09T10:00:00.000Z",
|
|
259
|
+
"retrieved_at": "2026-06-09T12:00:00.000Z",
|
|
260
|
+
"semantic_score": 1.7
|
|
261
|
+
}
|
|
262
|
+
```
|
|
261
263
|
|
|
262
264
|
## Relationship to Existing Core Types
|
|
263
265
|
|
|
@@ -270,16 +272,16 @@ The signal contract does not replace existing Core types:
|
|
|
270
272
|
|
|
271
273
|
The contract gives these surfaces a shared signal vocabulary without requiring Store, Worker, or MCP schema changes.
|
|
272
274
|
|
|
273
|
-
## Boundary
|
|
274
|
-
|
|
275
|
-
Signal Contract v1 does not determine truth, certify data, or provide legal, medical, tax, or financial advice. It provides normalized context metadata for freshness, provenance, relevance, and workflow review.
|
|
276
|
-
|
|
277
|
-
## Future Metadata Boundary
|
|
278
|
-
|
|
279
|
-
Future context signals, control signals, ingestion quality signals, structure preservation signals, and provenance confidence signals may later improve decisions such as `cite_as_primary`, `needs_refresh`, `needs_verification`, or `exclude`.
|
|
280
|
-
|
|
281
|
-
Those are roadmap metadata layers. They should remain optional until tests prove they improve decisions. The public input contract should stay boring and stable:
|
|
282
|
-
|
|
283
|
-
```text
|
|
284
|
-
title + content + source + source_type + published_at + retrieved_at + semantic_score
|
|
285
|
-
```
|
|
275
|
+
## Boundary
|
|
276
|
+
|
|
277
|
+
Signal Contract v1 does not determine truth, certify data, or provide legal, medical, tax, or financial advice. It provides normalized context metadata for freshness, provenance, relevance, and workflow review.
|
|
278
|
+
|
|
279
|
+
## Future Metadata Boundary
|
|
280
|
+
|
|
281
|
+
Future context signals, control signals, ingestion quality signals, structure preservation signals, and provenance confidence signals may later improve decisions such as `cite_as_primary`, `needs_refresh`, `needs_verification`, or `exclude`.
|
|
282
|
+
|
|
283
|
+
Those are roadmap metadata layers. They should remain optional until tests prove they improve decisions. The public input contract should stay boring and stable:
|
|
284
|
+
|
|
285
|
+
```text
|
|
286
|
+
title + content + source + source_type + published_at + retrieved_at + semantic_score
|
|
287
|
+
```
|
package/package-script-guard.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { spawnSync } from "node:child_process";
|
|
4
|
-
import { join } from "node:path";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { join } from "node:path";
|
|
5
5
|
|
|
6
6
|
const SOURCE_CHECKOUT_MESSAGE = [
|
|
7
7
|
"This npm script is for the FreshContext source checkout.",
|
|
@@ -40,19 +40,24 @@ const commands = {
|
|
|
40
40
|
command: "tsx",
|
|
41
41
|
args: ["examples/evaluate-with-source-profile.ts"],
|
|
42
42
|
},
|
|
43
|
-
"demo:evaluate:file": {
|
|
44
|
-
required: ["examples/evaluate-file.ts", "examples/sources.academic.example.json"],
|
|
45
|
-
command: "tsx",
|
|
46
|
-
args: ["examples/evaluate-file.ts", "examples/sources.academic.example.json"],
|
|
47
|
-
passThroughArgs: true,
|
|
48
|
-
},
|
|
49
|
-
"batch:validate": {
|
|
50
|
-
required: ["examples/validate-signal-batch.ts"],
|
|
51
|
-
command: "tsx",
|
|
52
|
-
args: ["examples/validate-signal-batch.ts"],
|
|
53
|
-
passThroughArgs: true,
|
|
54
|
-
},
|
|
55
|
-
"
|
|
43
|
+
"demo:evaluate:file": {
|
|
44
|
+
required: ["examples/evaluate-file.ts", "examples/sources.academic.example.json"],
|
|
45
|
+
command: "tsx",
|
|
46
|
+
args: ["examples/evaluate-file.ts", "examples/sources.academic.example.json"],
|
|
47
|
+
passThroughArgs: true,
|
|
48
|
+
},
|
|
49
|
+
"batch:validate": {
|
|
50
|
+
required: ["examples/validate-signal-batch.ts"],
|
|
51
|
+
command: "tsx",
|
|
52
|
+
args: ["examples/validate-signal-batch.ts"],
|
|
53
|
+
passThroughArgs: true,
|
|
54
|
+
},
|
|
55
|
+
"core:fixture": {
|
|
56
|
+
required: ["scripts/pack-core-fixture.mjs", "dist/core/index.js"],
|
|
57
|
+
command: "node",
|
|
58
|
+
args: ["scripts/pack-core-fixture.mjs"],
|
|
59
|
+
},
|
|
60
|
+
"smoke:stdio": {
|
|
56
61
|
required: ["scripts/smoke-stdio.mjs"],
|
|
57
62
|
command: "node",
|
|
58
63
|
args: ["scripts/smoke-stdio.mjs"],
|
|
@@ -98,20 +103,24 @@ const commands = {
|
|
|
98
103
|
"tests/freshnessStamp.test.ts",
|
|
99
104
|
"tests/hackernews.test.ts",
|
|
100
105
|
"tests/arxivSignals.test.ts",
|
|
101
|
-
"tests/arxivDecisionIntegration.test.ts",
|
|
102
|
-
"tests/core.test.ts",
|
|
103
|
-
"tests/haPriV2GoldenVectors.test.ts",
|
|
104
|
-
"tests/signalContractExamples.test.ts",
|
|
105
|
-
"tests/batchValidationHarness.test.ts",
|
|
106
|
-
"tests/rank.test.ts",
|
|
107
|
-
"tests/workerEnvelope.test.ts",
|
|
108
|
-
"tests/packageScriptGuard.test.mjs",
|
|
109
|
-
"tests/
|
|
110
|
-
"tests/
|
|
111
|
-
"tests/
|
|
106
|
+
"tests/arxivDecisionIntegration.test.ts",
|
|
107
|
+
"tests/core.test.ts",
|
|
108
|
+
"tests/haPriV2GoldenVectors.test.ts",
|
|
109
|
+
"tests/signalContractExamples.test.ts",
|
|
110
|
+
"tests/batchValidationHarness.test.ts",
|
|
111
|
+
"tests/rank.test.ts",
|
|
112
|
+
"tests/workerEnvelope.test.ts",
|
|
113
|
+
"tests/packageScriptGuard.test.mjs",
|
|
114
|
+
"tests/corePackageFixture.test.mjs",
|
|
115
|
+
"tests/readableOutput.test.ts",
|
|
116
|
+
"tests/provenanceReadiness.test.ts",
|
|
117
|
+
"tests/adapterNetworkBoundary.test.ts",
|
|
118
|
+
"tests/workerRouteSecurity.test.ts",
|
|
119
|
+
"tests/workerCoreEnvelopeParity.test.ts",
|
|
112
120
|
"tests/coreEnvelopeOptions.test.ts",
|
|
113
121
|
"tests/mathSpine.test.ts",
|
|
114
122
|
"tests/coreApiContract.test.ts",
|
|
123
|
+
"tests/coreSubpathExport.test.mjs",
|
|
115
124
|
"tests/corePipeline.test.ts",
|
|
116
125
|
"tests/decision.test.ts",
|
|
117
126
|
"tests/evaluateContextTool.test.ts",
|
|
@@ -131,54 +140,54 @@ if (!config) {
|
|
|
131
140
|
process.exit(1);
|
|
132
141
|
}
|
|
133
142
|
|
|
134
|
-
const hasSourceCheckoutFiles = config.required.every((path) => existsSync(path));
|
|
135
|
-
if (!hasSourceCheckoutFiles) {
|
|
136
|
-
console.log(SOURCE_CHECKOUT_MESSAGE);
|
|
137
|
-
process.exit(0);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function resolveCommand(command, args) {
|
|
141
|
-
if (command === "node") return { command: process.execPath, args };
|
|
142
|
-
|
|
143
|
-
const localNodeEntrypoints = {
|
|
144
|
-
tsx: join("node_modules", "tsx", "dist", "cli.mjs"),
|
|
145
|
-
tsc: join("node_modules", "typescript", "bin", "tsc"),
|
|
146
|
-
};
|
|
147
|
-
const nodeEntrypoint = localNodeEntrypoints[command];
|
|
148
|
-
if (nodeEntrypoint && existsSync(nodeEntrypoint)) {
|
|
149
|
-
return { command: process.execPath, args: [nodeEntrypoint, ...args] };
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const localBin = process.platform === "win32"
|
|
153
|
-
? join("node_modules", ".bin", `${command}.cmd`)
|
|
154
|
-
: join("node_modules", ".bin", command);
|
|
155
|
-
|
|
156
|
-
if (existsSync(localBin)) return { command: localBin, args };
|
|
157
|
-
if (process.platform === "win32" && !command.endsWith(".cmd")) {
|
|
158
|
-
return { command: `${command}.cmd`, args };
|
|
159
|
-
}
|
|
160
|
-
return { command, args };
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function validatePassThroughArgs(args) {
|
|
164
|
-
for (const arg of args) {
|
|
165
|
-
if (arg.includes("\0")) {
|
|
166
|
-
console.error("FreshContext package script arguments cannot contain null bytes.");
|
|
167
|
-
process.exit(1);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return args;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const args = [
|
|
174
|
-
...config.args,
|
|
175
|
-
...(config.passThroughArgs ? validatePassThroughArgs(process.argv.slice(3)) : []),
|
|
176
|
-
];
|
|
177
|
-
const invocation = resolveCommand(config.command, args);
|
|
178
|
-
const child = spawnSync(invocation.command, invocation.args, {
|
|
179
|
-
stdio: "inherit",
|
|
180
|
-
shell: false,
|
|
181
|
-
});
|
|
143
|
+
const hasSourceCheckoutFiles = config.required.every((path) => existsSync(path));
|
|
144
|
+
if (!hasSourceCheckoutFiles) {
|
|
145
|
+
console.log(SOURCE_CHECKOUT_MESSAGE);
|
|
146
|
+
process.exit(0);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function resolveCommand(command, args) {
|
|
150
|
+
if (command === "node") return { command: process.execPath, args };
|
|
151
|
+
|
|
152
|
+
const localNodeEntrypoints = {
|
|
153
|
+
tsx: join("node_modules", "tsx", "dist", "cli.mjs"),
|
|
154
|
+
tsc: join("node_modules", "typescript", "bin", "tsc"),
|
|
155
|
+
};
|
|
156
|
+
const nodeEntrypoint = localNodeEntrypoints[command];
|
|
157
|
+
if (nodeEntrypoint && existsSync(nodeEntrypoint)) {
|
|
158
|
+
return { command: process.execPath, args: [nodeEntrypoint, ...args] };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const localBin = process.platform === "win32"
|
|
162
|
+
? join("node_modules", ".bin", `${command}.cmd`)
|
|
163
|
+
: join("node_modules", ".bin", command);
|
|
164
|
+
|
|
165
|
+
if (existsSync(localBin)) return { command: localBin, args };
|
|
166
|
+
if (process.platform === "win32" && !command.endsWith(".cmd")) {
|
|
167
|
+
return { command: `${command}.cmd`, args };
|
|
168
|
+
}
|
|
169
|
+
return { command, args };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function validatePassThroughArgs(args) {
|
|
173
|
+
for (const arg of args) {
|
|
174
|
+
if (arg.includes("\0")) {
|
|
175
|
+
console.error("FreshContext package script arguments cannot contain null bytes.");
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return args;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const args = [
|
|
183
|
+
...config.args,
|
|
184
|
+
...(config.passThroughArgs ? validatePassThroughArgs(process.argv.slice(3)) : []),
|
|
185
|
+
];
|
|
186
|
+
const invocation = resolveCommand(config.command, args);
|
|
187
|
+
const child = spawnSync(invocation.command, invocation.args, {
|
|
188
|
+
stdio: "inherit",
|
|
189
|
+
shell: false,
|
|
190
|
+
});
|
|
182
191
|
|
|
183
192
|
if (child.error) {
|
|
184
193
|
console.error(child.error.message);
|