freshcontext-mcp 0.3.19 → 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 (75) hide show
  1. package/FRESHCONTEXT_SPEC.md +317 -0
  2. package/METHODOLOGY.md +381 -0
  3. package/README.md +55 -5
  4. package/SECURITY.md +9 -7
  5. package/dist/adapters/arxiv.d.ts +15 -0
  6. package/dist/adapters/arxiv.js +3 -2
  7. package/dist/adapters/changelog.d.ts +2 -0
  8. package/dist/adapters/changelog.js +4 -2
  9. package/dist/adapters/finance.d.ts +2 -0
  10. package/dist/adapters/finance.js +1 -1
  11. package/dist/adapters/gdelt.d.ts +2 -0
  12. package/dist/adapters/gdelt.js +1 -1
  13. package/dist/adapters/gebiz.d.ts +2 -0
  14. package/dist/adapters/gebiz.js +1 -1
  15. package/dist/adapters/github.d.ts +2 -0
  16. package/dist/adapters/govcontracts.d.ts +2 -0
  17. package/dist/adapters/hackernews.d.ts +2 -0
  18. package/dist/adapters/jobs.d.ts +2 -0
  19. package/dist/adapters/jobs.js +6 -6
  20. package/dist/adapters/packageTrends.d.ts +2 -0
  21. package/dist/adapters/productHunt.d.ts +2 -0
  22. package/dist/adapters/reddit.d.ts +8 -0
  23. package/dist/adapters/reddit.js +12 -5
  24. package/dist/adapters/registry.d.ts +19 -0
  25. package/dist/adapters/repoSearch.d.ts +2 -0
  26. package/dist/adapters/repoSearch.js +1 -1
  27. package/dist/adapters/scholar.d.ts +2 -0
  28. package/dist/adapters/secFilings.d.ts +2 -0
  29. package/dist/adapters/secFilings.js +1 -1
  30. package/dist/adapters/yc.d.ts +2 -0
  31. package/dist/core/decay.d.ts +5 -0
  32. package/dist/core/decision.d.ts +3 -0
  33. package/dist/core/decision.js +1 -3
  34. package/dist/core/envelope.d.ts +5 -0
  35. package/dist/core/envelope.js +9 -1
  36. package/dist/core/explain.d.ts +12 -0
  37. package/dist/core/guards.d.ts +1 -0
  38. package/dist/core/index.d.ts +14 -0
  39. package/dist/core/index.js +2 -0
  40. package/dist/core/pipeline.d.ts +3 -0
  41. package/dist/core/pipeline.js +8 -0
  42. package/dist/core/provenance.d.ts +5 -0
  43. package/dist/core/provenanceReadiness.d.ts +2 -0
  44. package/dist/core/provenanceReadiness.js +220 -0
  45. package/dist/core/rank.d.ts +4 -0
  46. package/dist/core/readable.d.ts +2 -0
  47. package/dist/core/readable.js +75 -0
  48. package/dist/core/signal.d.ts +3 -0
  49. package/dist/core/sourceProfiles.d.ts +4 -0
  50. package/dist/core/types.d.ts +239 -0
  51. package/dist/core/utility.d.ts +2 -0
  52. package/dist/rest/handler.d.ts +1 -0
  53. package/dist/security.d.ts +15 -0
  54. package/dist/security.js +3 -1
  55. package/dist/server.d.ts +2 -0
  56. package/dist/server.js +2 -2
  57. package/dist/tools/evaluateContext.d.ts +21 -0
  58. package/dist/tools/evaluateContext.js +22 -1
  59. package/dist/tools/freshnessStamp.d.ts +1 -0
  60. package/dist/types.d.ts +1 -0
  61. package/docs/API_DESIGN.md +28 -1
  62. package/docs/CLIENT_SETUP.md +166 -0
  63. package/docs/CODEX_MCP_USAGE.md +4 -4
  64. package/docs/CORE_API.md +69 -5
  65. package/docs/CORE_MCP_BOUNDARY.md +13 -4
  66. package/docs/FUTURE_LANES.md +26 -3
  67. package/docs/HA_PRI_V2_DESIGN.md +7 -1
  68. package/docs/HA_PRI_V2_PRODUCTION_ENFORCEMENT_PLAN.md +414 -0
  69. package/docs/HUMAN_READABLE_OUTPUT_CONTRACT.md +293 -0
  70. package/docs/RELEASE_INTEGRITY.md +1 -1
  71. package/docs/RELEASE_NOTES.md +33 -5
  72. package/docs/SIGNAL_CONTRACT.md +200 -2
  73. package/package-script-guard.mjs +59 -3
  74. package/package.json +33 -13
  75. package/server.json +2 -2
@@ -0,0 +1,293 @@
1
+ # Human-Readable Output Contract
2
+
3
+ Status: implemented MVP contract.
4
+
5
+ This document describes the reader-facing output layer over FreshContext Core decisions. The MVP is implemented as an additive Core helper and `evaluate_context` structured JSON field. It does not change Core behavior, ranking, decision labels, utility math, Worker behavior, package version, deployment state, or public site copy.
6
+
7
+ FreshContext is not truth itself. FreshContext records why context was trusted, down-ranked, questioned, refreshed, watched, backgrounded, or excluded before an AI system uses it.
8
+
9
+ ## Purpose
10
+
11
+ FreshContext Core already returns machine decisions, reasons, warnings, utility, freshness, confidence, Source Profile context, and provenance material. The human-readable output layer should make those results understandable without exposing every internal score first.
12
+
13
+ The output should answer:
14
+
15
+ - Can I use this context?
16
+ - Why was this source treated this way?
17
+ - What reached the model?
18
+ - What was kept out?
19
+ - Can another agent inherit this context safely?
20
+
21
+ ## Audiences
22
+
23
+ - Normal readers need a short status, reason, and warning.
24
+ - Analysts and buyers need an evidence table that shows why each source was treated differently.
25
+ - Developers need a stable JSON shape for future SDK, API, MCP, and CLI formatting.
26
+ - Multi-agent workflows need enough identity and judgment metadata for one agent to hand context to another without losing evidence boundaries.
27
+
28
+ ## Non-Goals
29
+
30
+ This contract does not:
31
+
32
+ - certify truth
33
+ - provide professional guidance in legal, clinical, tax, employment, academic, or financial domains
34
+ - change Core scoring or ranking
35
+ - make utility control decision labels
36
+ - wire adapters into Core
37
+ - add `evaluate_source`
38
+ - define a live hosted API response
39
+ - replace Signal Contract v1
40
+ - claim Ha-Pri v2 production enforcement
41
+
42
+ ## Decision Vocabulary
43
+
44
+ FreshContext should keep the current Core machine decisions as the stable machine layer.
45
+
46
+ | Machine decision | Reader label | Meaning | Human action | Agent action | Must not claim |
47
+ | --- | --- | --- | --- | --- | --- |
48
+ | `use_first` | Use first | Strong, current context for the task. | Read or place this near the top of the working context. | Prioritize in the context bundle. | This is guaranteed true. |
49
+ | `cite_as_primary` | Primary source | Relevant, current, and traceable enough to use as main evidence. | Use as main evidence while applying normal review. | Use as primary citation evidence. | This source proves the claim by itself. |
50
+ | `cite_as_supporting` | Supporting source | Useful evidence, but not enough to stand alone as the latest or strongest support. | Pair with a clearer, newer, or more authoritative source. | Include as supporting context, not sole evidence. | This is sufficient primary evidence. |
51
+ | `use_as_background` | Background only | Relevant context, but not strong enough for current-evidence claims. | Use for framing, history, or orientation. | Keep lower in the context bundle. | This is current proof. |
52
+ | `needs_verification` | Needs verification | Possibly useful, but timing, confidence, or traceability is uncertain. | Verify before relying on it. | Do not use as trusted primary context. | This source is false. |
53
+ | `needs_refresh` | Needs refresh | Possibly useful, but too stale or date-uncertain for this source type. | Re-query or find a newer source. | Refresh retrieval before use. | This source is useless or false. |
54
+ | `watch_only` | Watch only | Interesting signal, but not strong enough to prioritize. | Monitor or keep as weak signal. | Keep out of primary reasoning unless requested. | This is actionable evidence. |
55
+ | `exclude` | Excluded | Failed, too weak, unsafe, or not useful enough for the final context bundle. | Keep out unless manually reviewed. | Do not pass to the model as useful context. | This is legally or factually invalid. |
56
+
57
+ ## Reader Card
58
+
59
+ The Reader Card is for normal humans. It should be short and decision-first.
60
+
61
+ Example:
62
+
63
+ ```txt
64
+ Status: Primary source
65
+
66
+ Why:
67
+ Recent, directly relevant, and traceable enough for main evidence.
68
+
69
+ Watch-outs:
70
+ FreshContext does not certify truth.
71
+
72
+ What FreshContext did:
73
+ Ranked this source above weaker, stale, or unclear candidates before model use.
74
+ ```
75
+
76
+ Recommended fields:
77
+
78
+ - `status`
79
+ - `why`
80
+ - `watch_outs`
81
+ - `what_freshcontext_did`
82
+
83
+ The Reader Card should not lead with raw scores unless a technical user asks for them.
84
+
85
+ The current MVP is the `readable` object returned inside each structured `evaluate_context` result:
86
+
87
+ ```json
88
+ {
89
+ "decision": "cite_as_primary",
90
+ "label": "Cite as primary",
91
+ "readable": {
92
+ "label": "Primary source",
93
+ "summary": "This source is strong enough to use as main evidence.",
94
+ "why": [
95
+ "Strong semantic match and current freshness for arxiv.",
96
+ "source profile academic_research uses lenient date policy",
97
+ "intent profile citation_check selected"
98
+ ],
99
+ "action": "Use this as main evidence while preserving citation and provenance.",
100
+ "warnings": [
101
+ "FreshContext judges citation readiness and context usefulness; it does not certify truth."
102
+ ]
103
+ }
104
+ }
105
+ ```
106
+
107
+ `readable.why` is capped at five reasons to keep output readable and deterministic.
108
+
109
+ The readable object translates Core decisions into user-facing language. It does not change ranking, decision labels, utility scoring, or source intake.
110
+
111
+ ## Analyst Evidence Table
112
+
113
+ The Analyst Evidence Table is for buyers, reviewers, and smart non-technical readers who need to compare multiple sources.
114
+
115
+ Recommended columns:
116
+
117
+ | Column | Plain meaning |
118
+ | --- | --- |
119
+ | Decision | How FreshContext says this context should be treated. |
120
+ | Source | Where the context came from. |
121
+ | Usefulness | How helpful the context is for this question. |
122
+ | Freshness | Whether the timing is current enough for this use. |
123
+ | Confidence | How reliable the context signal appears. |
124
+ | Provenance | Whether source identity and audit metadata are preserved. |
125
+ | Reason | Short explanation of the treatment label. |
126
+ | Warning | Non-advice or verification warning, if any. |
127
+
128
+ Example row:
129
+
130
+ ```txt
131
+ Primary source | arxiv.org/... | High | Current | High | Clear | Recent, direct academic source | Does not certify truth
132
+ ```
133
+
134
+ ## Developer JSON Contract
135
+
136
+ This is a proposed future response shape for SDK, API, MCP, and CLI formatting. It is not a live API contract yet.
137
+
138
+ ```json
139
+ {
140
+ "context_id": "ctx_...",
141
+ "decision": "cite_as_primary",
142
+ "reader_label": "Primary source",
143
+ "summary": "Recent, directly relevant source with clear provenance.",
144
+ "source": {
145
+ "id": "src_...",
146
+ "url": "https://example.com/source",
147
+ "type": "academic_research",
148
+ "title": "Example source"
149
+ },
150
+ "scores": {
151
+ "rank": 0.92,
152
+ "freshness": 87,
153
+ "utility": 81,
154
+ "confidence": "high"
155
+ },
156
+ "provenance": {
157
+ "published_at": "2026-06-01T00:00:00.000Z",
158
+ "retrieved_at": "2026-06-09T00:00:00.000Z",
159
+ "hash": "sha256:..."
160
+ },
161
+ "reasons": [
162
+ "Strong semantic match and current freshness for arxiv."
163
+ ],
164
+ "warnings": [
165
+ "FreshContext judges citation readiness and context usefulness; it does not certify truth."
166
+ ],
167
+ "handoff": {
168
+ "safe_for_agent_handoff": true,
169
+ "handoff_notes": []
170
+ }
171
+ }
172
+ ```
173
+
174
+ The JSON layer should preserve the current Core decision label while adding a reader label and summary. It should not rename the machine decision.
175
+
176
+ ## Multi-Agent Handoff Contract
177
+
178
+ A multi-agent handoff should let Agent B understand what Agent A used, rejected, or questioned without re-reading the whole original prompt.
179
+
180
+ Required fields to consider:
181
+
182
+ - `context_id`
183
+ - `source_id`
184
+ - `decision`
185
+ - `reader_label`
186
+ - `source_profile`
187
+ - `intent_profile`
188
+ - `freshness_state`
189
+ - `confidence_state`
190
+ - `utility_state`
191
+ - `provenance_hash`
192
+ - `published_at`
193
+ - `retrieved_at`
194
+ - `judged_at`
195
+ - `judged_by`
196
+ - `handoff_safe`
197
+ - `handoff_reason`
198
+ - `reasons`
199
+ - `warnings`
200
+ - `excluded_context_refs`
201
+
202
+ Example:
203
+
204
+ ```json
205
+ {
206
+ "context_id": "ctx_123",
207
+ "source_id": "src_456",
208
+ "decision": "needs_verification",
209
+ "reader_label": "Needs verification",
210
+ "source_profile": "company_intel",
211
+ "intent_profile": "business_due_diligence",
212
+ "freshness_state": "unknown",
213
+ "confidence_state": "medium",
214
+ "utility_state": "partly useful",
215
+ "provenance_hash": "sha256:...",
216
+ "published_at": null,
217
+ "retrieved_at": "2026-06-09T00:00:00.000Z",
218
+ "judged_at": "2026-06-09T00:00:00.000Z",
219
+ "judged_by": "freshcontext-core",
220
+ "handoff_safe": false,
221
+ "handoff_reason": "Useful but missing source date; verify before primary use.",
222
+ "reasons": [
223
+ "published_at/content_date was invalid; cleared"
224
+ ],
225
+ "warnings": [
226
+ "FreshContext supports context triage only; it is not professional legal, tax, or financial guidance."
227
+ ],
228
+ "excluded_context_refs": []
229
+ }
230
+ ```
231
+
232
+ ## Utility Language
233
+
234
+ Utility means usefulness for the current question. It does not mean truth.
235
+
236
+ Allowed wording:
237
+
238
+ - High utility: useful for this question
239
+ - Medium utility: partly useful
240
+ - Low utility: weak fit for this question
241
+
242
+ Forbidden wording:
243
+
244
+ - true
245
+ - verified truth
246
+ - claims that accuracy is guaranteed
247
+ - claims that a source has official approval
248
+ - claims that FreshContext has settled the answer
249
+
250
+ Utility can appear in explanations and reasons, but it must not be described as controlling default decision labels unless a future policy pass explicitly changes that behavior.
251
+
252
+ ## Provenance Language
253
+
254
+ Provenance means traceable source identity and audit material. It does not mean magical truth.
255
+
256
+ Allowed wording:
257
+
258
+ - clear provenance
259
+ - unclear provenance
260
+ - source identity preserved
261
+ - retrieval time recorded
262
+ - source timestamp recorded
263
+ - deterministic audit hash
264
+
265
+ Forbidden wording:
266
+
267
+ - absolute tamper resistance
268
+ - truth certification claims
269
+ - legal verification claims
270
+ - outside audit claims
271
+ - origin-authenticated unless a future signing model provides that guarantee
272
+
273
+ ## Forbidden Claims
274
+
275
+ FreshContext output must not claim:
276
+
277
+ - it determines truth
278
+ - it proves correctness
279
+ - it replaces human review
280
+ - it is a legal, medical, tax, employment, academic, or investment advisor
281
+ - it validates facts beyond the provided context metadata
282
+ - it guarantees source authenticity
283
+ - it has production Ha-Pri v2 enforcement unless that enforcement is actually implemented
284
+
285
+ ## Future Implementation Passes
286
+
287
+ Suggested next passes:
288
+
289
+ - Pass 14-D: review whether the Analyst Evidence Table should become a helper or stay documentation-only.
290
+ - Pass 14-E: decide whether to add human-readable text lines to `evaluate_context`, or keep the readable layer JSON-only.
291
+ - Later: design Diagnostic Mode on top of `why`, `warnings`, and replay mismatch evidence.
292
+
293
+ The MVP is intentionally small: it translates existing judgment into readable output without changing the judgment itself.
@@ -22,7 +22,7 @@ This document describes release hardening practices for future FreshContext pack
22
22
  - Confirm fresh consumer `npm audit --omit=dev` is clean.
23
23
  - Run a stale-claim scan across public docs and package-facing files.
24
24
  - Run a secret scan before sharing archives, diligence folders, or package artifacts.
25
- - Keep operational demo runbooks, buyer scripts, outreach plans, diligence checklists, and negotiation materials outside the public npm package.
25
+ - Keep operational demo runbooks, buyer scripts, outreach plans, diligence checklists, and private commercial materials outside the public npm package.
26
26
 
27
27
  ## Package Exclusion Checks
28
28
 
@@ -1,8 +1,36 @@
1
- # FreshContext Release Notes
2
-
3
- ## 0.3.19
4
-
5
- FreshContext 0.3.19 syncs the public MCP package with the new generic `evaluate_context` interface.
1
+ # FreshContext Release Notes
2
+
3
+ ## 0.3.21
4
+
5
+ FreshContext 0.3.21 adds provenance readiness and readable handoff safety for judged context.
6
+
7
+ ### Provenance Readiness
8
+
9
+ - Adds a Core `provenance_readiness` sidecar that classifies caller-provided context as `complete`, `partial`, `incomplete`, `unknown`, or `derived`.
10
+ - Keeps provenance readiness additive: it does not fetch sources, verify truth, change ranking, change utility scoring, or change decision-label policy.
11
+ - Preserves stable structured `evaluate_context` output while adding provenance readiness to each result.
12
+
13
+ ### Public Contract and Boundary Gates
14
+
15
+ - Adds compatibility coverage for pre-provenance `evaluate_context` payloads.
16
+ - Locks Core public imports, package fixture behavior, and the `freshcontext-mcp/core` subpath surface.
17
+ - Audits the adapter boundary so Core remains the judgment layer, while the 21 reference tools remain optional source-intake adapters.
18
+
19
+ ### Readable Handoff Safety
20
+
21
+ - Adds `readable.handoff.safe_for_agent_handoff` and `readable.handoff.reason` to structured readable output.
22
+ - Derives handoff safety only from the existing decision and `provenance_readiness`.
23
+ - Does not add multi-agent orchestration, batch handoff counts, new MCP tools, or adapter orchestration.
24
+
25
+ ### Release Gate
26
+
27
+ - Adds stress coverage for ugly provenance, scoring, decision, readable output, and handoff edge cases.
28
+ - Pins the policy that minimal title-only legacy input is valid but needs verification.
29
+ - Confirms MCP smoke remains at 22 tools and package/server metadata align at 0.3.21 for this release prep.
30
+
31
+ ## 0.3.19
32
+
33
+ FreshContext 0.3.19 syncs the public MCP package with the new generic `evaluate_context` interface.
6
34
 
7
35
  ### Context Evaluation Front Door
8
36
 
@@ -1,9 +1,33 @@
1
1
  # FreshContext Signal Contract v1
2
2
 
3
- FreshContext Signal Contract v1 defines the Core shape for a retrieved signal before it is ranked, wrapped, stored, or passed to an agent workflow.
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.
4
14
 
5
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.
6
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.
30
+
7
31
  ## Contract Version
8
32
 
9
33
  ```ts
@@ -18,7 +42,7 @@ contract_version: "freshcontext.signal.v1"
18
42
 
19
43
  ## Input Shape
20
44
 
21
- `FreshContextSignalInput` accepts the common fields used by adapters, agents, ranking, and future Store wiring:
45
+ `FreshContextSignalInput` accepts the common fields used by adapters, agents, ranking, `evaluate_context`, and future Store wiring:
22
46
 
23
47
  ```ts
24
48
  interface FreshContextSignalInput {
@@ -40,6 +64,20 @@ interface FreshContextSignalInput {
40
64
 
41
65
  `published_at` is the canonical signal timestamp. `content_date` is accepted as an adapter/envelope compatibility alias.
42
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
+ ```
80
+
43
81
  ## Normalized Output
44
82
 
45
83
  `normalizeSignal(input, options?)` returns a `FreshContextSignal`:
@@ -73,6 +111,156 @@ interface FreshContextSignal {
73
111
  - `metadata` is shallow-copied so normalization does not mutate caller-owned objects.
74
112
  - `reasons` records meaningful normalization changes.
75
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
+ ```
263
+
76
264
  ## Relationship to Existing Core Types
77
265
 
78
266
  The signal contract does not replace existing Core types:
@@ -87,3 +275,13 @@ The contract gives these surfaces a shared signal vocabulary without requiring S
87
275
  ## Boundary
88
276
 
89
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
+ ```
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { existsSync } from "node:fs";
3
3
  import { spawnSync } from "node:child_process";
4
+ import { join } from "node:path";
4
5
 
5
6
  const SOURCE_CHECKOUT_MESSAGE = [
6
7
  "This npm script is for the FreshContext source checkout.",
@@ -45,6 +46,17 @@ const commands = {
45
46
  args: ["examples/evaluate-file.ts", "examples/sources.academic.example.json"],
46
47
  passThroughArgs: true,
47
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
+ },
48
60
  "smoke:stdio": {
49
61
  required: ["scripts/smoke-stdio.mjs"],
50
62
  command: "node",
@@ -93,12 +105,22 @@ const commands = {
93
105
  "tests/arxivSignals.test.ts",
94
106
  "tests/arxivDecisionIntegration.test.ts",
95
107
  "tests/core.test.ts",
108
+ "tests/haPriV2GoldenVectors.test.ts",
109
+ "tests/signalContractExamples.test.ts",
110
+ "tests/batchValidationHarness.test.ts",
96
111
  "tests/rank.test.ts",
97
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",
98
119
  "tests/workerCoreEnvelopeParity.test.ts",
99
120
  "tests/coreEnvelopeOptions.test.ts",
100
121
  "tests/mathSpine.test.ts",
101
122
  "tests/coreApiContract.test.ts",
123
+ "tests/coreSubpathExport.test.mjs",
102
124
  "tests/corePipeline.test.ts",
103
125
  "tests/decision.test.ts",
104
126
  "tests/evaluateContextTool.test.ts",
@@ -124,13 +146,47 @@ if (!hasSourceCheckoutFiles) {
124
146
  process.exit(0);
125
147
  }
126
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
+
127
182
  const args = [
128
183
  ...config.args,
129
- ...(config.passThroughArgs ? process.argv.slice(3) : []),
184
+ ...(config.passThroughArgs ? validatePassThroughArgs(process.argv.slice(3)) : []),
130
185
  ];
131
- const child = spawnSync(config.command, args, {
186
+ const invocation = resolveCommand(config.command, args);
187
+ const child = spawnSync(invocation.command, invocation.args, {
132
188
  stdio: "inherit",
133
- shell: process.platform === "win32",
189
+ shell: false,
134
190
  });
135
191
 
136
192
  if (child.error) {