@gmickel/gno 2.3.2 → 2.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.
Files changed (88) hide show
  1. package/README.md +24 -4
  2. package/assets/skill/SKILL.md +30 -0
  3. package/assets/skill/cli-reference.md +12 -0
  4. package/assets/skill/examples.md +15 -0
  5. package/assets/skill/mcp-reference.md +16 -0
  6. package/assets/spa-production.json.gz +0 -0
  7. package/browser-extension/artifacts/{gno-browser-clipper-v2.3.2.zip → gno-browser-clipper-v2.4.0.zip} +0 -0
  8. package/browser-extension/artifacts/gno-browser-clipper-v2.4.0.zip.sha256 +1 -0
  9. package/browser-extension/dist/manifest.json +1 -1
  10. package/package.json +1 -1
  11. package/spec/cli.md +30 -0
  12. package/spec/db/schema.sql +2 -0
  13. package/spec/evals.md +48 -0
  14. package/spec/mcp.md +12 -0
  15. package/spec/output-schemas/ask.schema.json +12 -0
  16. package/spec/output-schemas/context-capsule-v1.schema.json +205 -32
  17. package/spec/output-schemas/context-capsule-verification.schema.json +32 -9
  18. package/spec/output-schemas/evidence-fixtures.schema.json +176 -0
  19. package/spec/output-schemas/evidence-report.schema.json +322 -0
  20. package/spec/output-schemas/evidence-run.schema.json +277 -0
  21. package/spec/output-schemas/metadata-predicate.schema.json +460 -0
  22. package/spec/output-schemas/retrieval-trace-filters.schema.json +13 -4
  23. package/spec/output-schemas/search-results.schema.json +12 -0
  24. package/spec/output-schemas/status.schema.json +37 -6
  25. package/src/app/context-runtime-contract.ts +33 -2
  26. package/src/app/context-runtime-input.ts +17 -0
  27. package/src/app/context-runtime-types.ts +2 -0
  28. package/src/app/context-runtime.ts +27 -3
  29. package/src/app/context-surface.ts +2 -0
  30. package/src/app/verified-ask.ts +1 -0
  31. package/src/cli/commands/ask.ts +1 -0
  32. package/src/cli/commands/context-build.ts +1 -0
  33. package/src/cli/commands/search.ts +1 -0
  34. package/src/cli/commands/status.ts +10 -0
  35. package/src/cli/options.ts +19 -0
  36. package/src/cli/program.ts +12 -0
  37. package/src/converters/types.ts +2 -0
  38. package/src/core/context-capsule-retrieval-schema.ts +8 -0
  39. package/src/core/context-capsule-schema.ts +47 -3
  40. package/src/core/context-capsule-validation.ts +14 -2
  41. package/src/core/context-capsule-verification.ts +1 -0
  42. package/src/core/context-capsule.ts +16 -2
  43. package/src/core/context-compiler.ts +3 -0
  44. package/src/core/record-metadata.ts +1 -1
  45. package/src/core/retrieval-replay-candidate.ts +5 -0
  46. package/src/core/retrieval-trace-filter-normalization.ts +4 -0
  47. package/src/core/retrieval-trace-request.ts +1 -0
  48. package/src/core/retrieval-trace-session.ts +5 -1
  49. package/src/core/retrieval-trace.ts +2 -0
  50. package/src/core/typed-metadata.ts +224 -0
  51. package/src/ingestion/record-adapter-canonical.ts +13 -2
  52. package/src/ingestion/record-container.ts +9 -0
  53. package/src/ingestion/sync.ts +11 -1
  54. package/src/ingestion/typed-metadata.ts +55 -0
  55. package/src/mcp/tools/ask.ts +10 -2
  56. package/src/mcp/tools/context.ts +1 -0
  57. package/src/mcp/tools/index.ts +12 -1
  58. package/src/mcp/tools/query.ts +13 -0
  59. package/src/mcp/tools/search.ts +9 -0
  60. package/src/mcp/tools/status.ts +4 -0
  61. package/src/mcp/tools/vsearch.ts +9 -0
  62. package/src/pipeline/diagnose.ts +6 -0
  63. package/src/pipeline/filters.ts +65 -0
  64. package/src/pipeline/graph-retrieval.ts +9 -1
  65. package/src/pipeline/hybrid.ts +22 -2
  66. package/src/pipeline/search.ts +11 -0
  67. package/src/pipeline/types.ts +7 -1
  68. package/src/pipeline/vsearch.ts +21 -1
  69. package/src/sdk/client.ts +29 -1
  70. package/src/sdk/index.ts +4 -0
  71. package/src/sdk/types.ts +7 -0
  72. package/src/serve/context-capsule.ts +1 -0
  73. package/src/serve/public/app.tsx +1 -1
  74. package/src/serve/public/components/MetadataFilter.tsx +186 -0
  75. package/src/serve/public/globals.built.css +1 -1
  76. package/src/serve/public/lib/metadata-filter.ts +28 -0
  77. package/src/serve/public/lib/retrieval-filters.ts +3 -0
  78. package/src/serve/public/pages/Ask.tsx +48 -3
  79. package/src/serve/public/pages/DocView.tsx +33 -0
  80. package/src/serve/public/pages/Search.tsx +44 -1
  81. package/src/serve/routes/api.ts +50 -0
  82. package/src/store/migrations/030-typed-metadata.ts +13 -0
  83. package/src/store/migrations/index.ts +2 -0
  84. package/src/store/sqlite/adapter.ts +55 -4
  85. package/src/store/sqlite/eligibility.ts +12 -0
  86. package/src/store/sqlite/metadata-predicate.ts +71 -0
  87. package/src/store/types.ts +11 -0
  88. package/browser-extension/artifacts/gno-browser-clipper-v2.3.2.zip.sha256 +0 -1
@@ -0,0 +1,460 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "oneOf": [
4
+ {
5
+ "$ref": "#/definitions/__schema0"
6
+ },
7
+ {
8
+ "$ref": "#/definitions/__schema3"
9
+ },
10
+ {
11
+ "$ref": "#/definitions/__schema4"
12
+ },
13
+ {
14
+ "$ref": "#/definitions/__schema5"
15
+ },
16
+ {
17
+ "$ref": "#/definitions/__schema6"
18
+ },
19
+ {
20
+ "$ref": "#/definitions/__schema14"
21
+ }
22
+ ],
23
+ "definitions": {
24
+ "__schema0": {
25
+ "type": "object",
26
+ "properties": {
27
+ "op": {
28
+ "type": "string",
29
+ "enum": ["eq", "ne"]
30
+ },
31
+ "key": {
32
+ "$ref": "#/definitions/__schema1"
33
+ },
34
+ "value": {
35
+ "$ref": "#/definitions/__schema2"
36
+ }
37
+ },
38
+ "required": ["op", "key", "value"],
39
+ "additionalProperties": false
40
+ },
41
+ "__schema1": {
42
+ "type": "string",
43
+ "minLength": 1,
44
+ "maxLength": 128
45
+ },
46
+ "__schema2": {
47
+ "anyOf": [
48
+ {
49
+ "type": "string",
50
+ "maxLength": 4096
51
+ },
52
+ {
53
+ "type": "number"
54
+ },
55
+ {
56
+ "type": "boolean"
57
+ }
58
+ ]
59
+ },
60
+ "__schema3": {
61
+ "type": "object",
62
+ "properties": {
63
+ "op": {
64
+ "type": "string",
65
+ "enum": ["gt", "gte", "lt", "lte"]
66
+ },
67
+ "key": {
68
+ "$ref": "#/definitions/__schema1"
69
+ },
70
+ "value": {
71
+ "type": "number"
72
+ }
73
+ },
74
+ "required": ["op", "key", "value"],
75
+ "additionalProperties": false
76
+ },
77
+ "__schema4": {
78
+ "type": "object",
79
+ "properties": {
80
+ "op": {
81
+ "type": "string",
82
+ "enum": ["in", "nin", "all"]
83
+ },
84
+ "key": {
85
+ "$ref": "#/definitions/__schema1"
86
+ },
87
+ "values": {
88
+ "maxItems": 128,
89
+ "type": "array",
90
+ "items": {
91
+ "$ref": "#/definitions/__schema2"
92
+ }
93
+ }
94
+ },
95
+ "required": ["op", "key", "values"],
96
+ "additionalProperties": false
97
+ },
98
+ "__schema5": {
99
+ "type": "object",
100
+ "properties": {
101
+ "op": {
102
+ "type": "string",
103
+ "const": "exists"
104
+ },
105
+ "key": {
106
+ "$ref": "#/definitions/__schema1"
107
+ },
108
+ "value": {
109
+ "type": "boolean"
110
+ }
111
+ },
112
+ "required": ["op", "key", "value"],
113
+ "additionalProperties": false
114
+ },
115
+ "__schema6": {
116
+ "type": "object",
117
+ "properties": {
118
+ "op": {
119
+ "type": "string",
120
+ "enum": ["and", "or"]
121
+ },
122
+ "predicates": {
123
+ "minItems": 1,
124
+ "maxItems": 128,
125
+ "type": "array",
126
+ "items": {
127
+ "$ref": "#/definitions/__schema7"
128
+ }
129
+ }
130
+ },
131
+ "required": ["op", "predicates"],
132
+ "additionalProperties": false
133
+ },
134
+ "__schema7": {
135
+ "oneOf": [
136
+ {
137
+ "$ref": "#/definitions/__schema0"
138
+ },
139
+ {
140
+ "$ref": "#/definitions/__schema3"
141
+ },
142
+ {
143
+ "$ref": "#/definitions/__schema4"
144
+ },
145
+ {
146
+ "$ref": "#/definitions/__schema5"
147
+ },
148
+ {
149
+ "type": "object",
150
+ "properties": {
151
+ "op": {
152
+ "type": "string",
153
+ "enum": ["and", "or"]
154
+ },
155
+ "predicates": {
156
+ "minItems": 1,
157
+ "maxItems": 128,
158
+ "type": "array",
159
+ "items": {
160
+ "$ref": "#/definitions/__schema8"
161
+ }
162
+ }
163
+ },
164
+ "required": ["op", "predicates"],
165
+ "additionalProperties": false
166
+ },
167
+ {
168
+ "type": "object",
169
+ "properties": {
170
+ "op": {
171
+ "type": "string",
172
+ "const": "not"
173
+ },
174
+ "predicate": {
175
+ "$ref": "#/definitions/__schema8"
176
+ }
177
+ },
178
+ "required": ["op", "predicate"],
179
+ "additionalProperties": false
180
+ }
181
+ ]
182
+ },
183
+ "__schema8": {
184
+ "oneOf": [
185
+ {
186
+ "$ref": "#/definitions/__schema0"
187
+ },
188
+ {
189
+ "$ref": "#/definitions/__schema3"
190
+ },
191
+ {
192
+ "$ref": "#/definitions/__schema4"
193
+ },
194
+ {
195
+ "$ref": "#/definitions/__schema5"
196
+ },
197
+ {
198
+ "type": "object",
199
+ "properties": {
200
+ "op": {
201
+ "type": "string",
202
+ "enum": ["and", "or"]
203
+ },
204
+ "predicates": {
205
+ "minItems": 1,
206
+ "maxItems": 128,
207
+ "type": "array",
208
+ "items": {
209
+ "$ref": "#/definitions/__schema9"
210
+ }
211
+ }
212
+ },
213
+ "required": ["op", "predicates"],
214
+ "additionalProperties": false
215
+ },
216
+ {
217
+ "type": "object",
218
+ "properties": {
219
+ "op": {
220
+ "type": "string",
221
+ "const": "not"
222
+ },
223
+ "predicate": {
224
+ "$ref": "#/definitions/__schema9"
225
+ }
226
+ },
227
+ "required": ["op", "predicate"],
228
+ "additionalProperties": false
229
+ }
230
+ ]
231
+ },
232
+ "__schema9": {
233
+ "oneOf": [
234
+ {
235
+ "$ref": "#/definitions/__schema0"
236
+ },
237
+ {
238
+ "$ref": "#/definitions/__schema3"
239
+ },
240
+ {
241
+ "$ref": "#/definitions/__schema4"
242
+ },
243
+ {
244
+ "$ref": "#/definitions/__schema5"
245
+ },
246
+ {
247
+ "type": "object",
248
+ "properties": {
249
+ "op": {
250
+ "type": "string",
251
+ "enum": ["and", "or"]
252
+ },
253
+ "predicates": {
254
+ "minItems": 1,
255
+ "maxItems": 128,
256
+ "type": "array",
257
+ "items": {
258
+ "$ref": "#/definitions/__schema10"
259
+ }
260
+ }
261
+ },
262
+ "required": ["op", "predicates"],
263
+ "additionalProperties": false
264
+ },
265
+ {
266
+ "type": "object",
267
+ "properties": {
268
+ "op": {
269
+ "type": "string",
270
+ "const": "not"
271
+ },
272
+ "predicate": {
273
+ "$ref": "#/definitions/__schema10"
274
+ }
275
+ },
276
+ "required": ["op", "predicate"],
277
+ "additionalProperties": false
278
+ }
279
+ ]
280
+ },
281
+ "__schema10": {
282
+ "oneOf": [
283
+ {
284
+ "$ref": "#/definitions/__schema0"
285
+ },
286
+ {
287
+ "$ref": "#/definitions/__schema3"
288
+ },
289
+ {
290
+ "$ref": "#/definitions/__schema4"
291
+ },
292
+ {
293
+ "$ref": "#/definitions/__schema5"
294
+ },
295
+ {
296
+ "type": "object",
297
+ "properties": {
298
+ "op": {
299
+ "type": "string",
300
+ "enum": ["and", "or"]
301
+ },
302
+ "predicates": {
303
+ "minItems": 1,
304
+ "maxItems": 128,
305
+ "type": "array",
306
+ "items": {
307
+ "$ref": "#/definitions/__schema11"
308
+ }
309
+ }
310
+ },
311
+ "required": ["op", "predicates"],
312
+ "additionalProperties": false
313
+ },
314
+ {
315
+ "type": "object",
316
+ "properties": {
317
+ "op": {
318
+ "type": "string",
319
+ "const": "not"
320
+ },
321
+ "predicate": {
322
+ "$ref": "#/definitions/__schema11"
323
+ }
324
+ },
325
+ "required": ["op", "predicate"],
326
+ "additionalProperties": false
327
+ }
328
+ ]
329
+ },
330
+ "__schema11": {
331
+ "oneOf": [
332
+ {
333
+ "$ref": "#/definitions/__schema0"
334
+ },
335
+ {
336
+ "$ref": "#/definitions/__schema3"
337
+ },
338
+ {
339
+ "$ref": "#/definitions/__schema4"
340
+ },
341
+ {
342
+ "$ref": "#/definitions/__schema5"
343
+ },
344
+ {
345
+ "type": "object",
346
+ "properties": {
347
+ "op": {
348
+ "type": "string",
349
+ "enum": ["and", "or"]
350
+ },
351
+ "predicates": {
352
+ "minItems": 1,
353
+ "maxItems": 128,
354
+ "type": "array",
355
+ "items": {
356
+ "$ref": "#/definitions/__schema12"
357
+ }
358
+ }
359
+ },
360
+ "required": ["op", "predicates"],
361
+ "additionalProperties": false
362
+ },
363
+ {
364
+ "type": "object",
365
+ "properties": {
366
+ "op": {
367
+ "type": "string",
368
+ "const": "not"
369
+ },
370
+ "predicate": {
371
+ "$ref": "#/definitions/__schema12"
372
+ }
373
+ },
374
+ "required": ["op", "predicate"],
375
+ "additionalProperties": false
376
+ }
377
+ ]
378
+ },
379
+ "__schema12": {
380
+ "oneOf": [
381
+ {
382
+ "$ref": "#/definitions/__schema0"
383
+ },
384
+ {
385
+ "$ref": "#/definitions/__schema3"
386
+ },
387
+ {
388
+ "$ref": "#/definitions/__schema4"
389
+ },
390
+ {
391
+ "$ref": "#/definitions/__schema5"
392
+ },
393
+ {
394
+ "type": "object",
395
+ "properties": {
396
+ "op": {
397
+ "type": "string",
398
+ "enum": ["and", "or"]
399
+ },
400
+ "predicates": {
401
+ "minItems": 1,
402
+ "maxItems": 128,
403
+ "type": "array",
404
+ "items": {
405
+ "$ref": "#/definitions/__schema13"
406
+ }
407
+ }
408
+ },
409
+ "required": ["op", "predicates"],
410
+ "additionalProperties": false
411
+ },
412
+ {
413
+ "type": "object",
414
+ "properties": {
415
+ "op": {
416
+ "type": "string",
417
+ "const": "not"
418
+ },
419
+ "predicate": {
420
+ "$ref": "#/definitions/__schema13"
421
+ }
422
+ },
423
+ "required": ["op", "predicate"],
424
+ "additionalProperties": false
425
+ }
426
+ ]
427
+ },
428
+ "__schema13": {
429
+ "oneOf": [
430
+ {
431
+ "$ref": "#/definitions/__schema0"
432
+ },
433
+ {
434
+ "$ref": "#/definitions/__schema3"
435
+ },
436
+ {
437
+ "$ref": "#/definitions/__schema4"
438
+ },
439
+ {
440
+ "$ref": "#/definitions/__schema5"
441
+ }
442
+ ]
443
+ },
444
+ "__schema14": {
445
+ "type": "object",
446
+ "properties": {
447
+ "op": {
448
+ "type": "string",
449
+ "const": "not"
450
+ },
451
+ "predicate": {
452
+ "$ref": "#/definitions/__schema7"
453
+ }
454
+ },
455
+ "required": ["op", "predicate"],
456
+ "additionalProperties": false
457
+ }
458
+ },
459
+ "$id": "gno://schemas/metadata-predicate@1.0"
460
+ }
@@ -8,7 +8,9 @@
8
8
  "additionalProperties": false,
9
9
  "required": ["mode", "text"],
10
10
  "properties": {
11
- "mode": { "enum": ["term", "intent", "hyde"] },
11
+ "mode": {
12
+ "enum": ["term", "intent", "hyde"]
13
+ },
12
14
  "text": { "type": "string", "maxLength": 8192 }
13
15
  }
14
16
  },
@@ -63,7 +65,10 @@
63
65
  "maxItems": 100,
64
66
  "items": { "$ref": "#/definitions/queryMode" }
65
67
  },
66
- "uriPrefix": { "type": "string", "maxLength": 4096 }
68
+ "uriPrefix": { "type": "string", "maxLength": 4096 },
69
+ "filter": {
70
+ "$ref": "gno://schemas/metadata-predicate@1.0"
71
+ }
67
72
  }
68
73
  },
69
74
  "metadataShape": {
@@ -133,7 +138,11 @@
133
138
  }
134
139
  },
135
140
  "oneOf": [
136
- { "$ref": "#/definitions/filters" },
137
- { "$ref": "#/definitions/metadataFilters" }
141
+ {
142
+ "$ref": "#/definitions/filters"
143
+ },
144
+ {
145
+ "$ref": "#/definitions/metadataFilters"
146
+ }
138
147
  ]
139
148
  }
@@ -408,6 +408,18 @@
408
408
  "description": "Search metadata",
409
409
  "required": ["query", "mode", "totalResults"],
410
410
  "properties": {
411
+ "warnings": {
412
+ "type": "array",
413
+ "items": {
414
+ "type": "object",
415
+ "additionalProperties": false,
416
+ "required": ["code", "message"],
417
+ "properties": {
418
+ "code": { "type": "string" },
419
+ "message": { "type": "string" }
420
+ }
421
+ }
422
+ },
411
423
  "query": {
412
424
  "type": "string",
413
425
  "description": "Original search query"
@@ -35,19 +35,31 @@
35
35
  "pendingMirrors"
36
36
  ],
37
37
  "properties": {
38
- "configured": { "$ref": "#/properties/chunking/definitions/params" },
38
+ "configured": {
39
+ "$ref": "#/properties/chunking/definitions/params"
40
+ },
39
41
  "applied": {
40
42
  "oneOf": [
41
- { "$ref": "#/properties/chunking/definitions/params" },
42
- { "type": "null" }
43
+ {
44
+ "$ref": "#/properties/chunking/definitions/params"
45
+ },
46
+ {
47
+ "type": "null"
48
+ }
43
49
  ]
44
50
  },
45
51
  "state": {
46
52
  "type": "string",
47
53
  "enum": ["empty", "legacy-default", "current", "pending", "mixed"]
48
54
  },
49
- "pendingDocuments": { "type": "integer", "minimum": 0 },
50
- "pendingMirrors": { "type": "integer", "minimum": 0 }
55
+ "pendingDocuments": {
56
+ "type": "integer",
57
+ "minimum": 0
58
+ },
59
+ "pendingMirrors": {
60
+ "type": "integer",
61
+ "minimum": 0
62
+ }
51
63
  },
52
64
  "definitions": {
53
65
  "params": {
@@ -60,7 +72,11 @@
60
72
  "minimum": 10,
61
73
  "maximum": 2251799813685247
62
74
  },
63
- "overlapPercent": { "type": "number", "minimum": 0, "maximum": 0.5 }
75
+ "overlapPercent": {
76
+ "type": "number",
77
+ "minimum": 0,
78
+ "maximum": 0.5
79
+ }
64
80
  }
65
81
  }
66
82
  }
@@ -951,6 +967,21 @@
951
967
  }
952
968
  }
953
969
  }
970
+ },
971
+ "typedMetadata": {
972
+ "type": "object",
973
+ "additionalProperties": false,
974
+ "required": ["pending", "invalid"],
975
+ "properties": {
976
+ "pending": {
977
+ "type": "integer",
978
+ "minimum": 0
979
+ },
980
+ "invalid": {
981
+ "type": "integer",
982
+ "minimum": 0
983
+ }
984
+ }
954
985
  }
955
986
  }
956
987
  }
@@ -154,7 +154,8 @@ export const projectContextCapsule = (
154
154
  egressLineage: ContextCapsulePayloadV1_1["egressLineage"];
155
155
  },
156
156
  input: NormalizedContextBuildInput,
157
- deps: ContextCapsuleRuntimeDeps
157
+ deps: ContextCapsuleRuntimeDeps,
158
+ metadataCoverageIncomplete = false
158
159
  ): ContextCanonicalProjection<ContextCapsuleV1> | null => {
159
160
  if (draft.selection.selected.length === 0) return null;
160
161
  const evidence = draft.selection.selected.map((candidate, index) =>
@@ -286,7 +287,37 @@ export const projectContextCapsule = (
286
287
  ],
287
288
  };
288
289
  try {
289
- const value = createContextCapsuleV1(payload, {
290
+ const versionedPayload =
291
+ input.filter === undefined
292
+ ? payload
293
+ : {
294
+ ...payload,
295
+ schemaVersion: "1.2" as const,
296
+ coverage: {
297
+ ...payload.coverage,
298
+ complete:
299
+ payload.coverage.complete && !metadataCoverageIncomplete,
300
+ },
301
+ warnings: [
302
+ ...payload.warnings,
303
+ ...(metadataCoverageIncomplete && payload.coverage.complete
304
+ ? [{ code: "incomplete_coverage" as const }]
305
+ : []),
306
+ ...(metadataCoverageIncomplete
307
+ ? [{ code: "metadata_coverage_incomplete" as const }]
308
+ : []),
309
+ ],
310
+ scope: { ...payload.scope, filter: input.filter },
311
+ retrieval: {
312
+ ...payload.retrieval,
313
+ request: { ...payload.retrieval.request, filter: input.filter },
314
+ },
315
+ };
316
+ versionedPayload.fingerprints.retrieval = retrievalFingerprint(
317
+ versionedPayload,
318
+ snapshots.contextFingerprint
319
+ );
320
+ const value = createContextCapsuleV1(versionedPayload, {
290
321
  countTokens: deps.countTokens,
291
322
  });
292
323
  return {
@@ -5,6 +5,10 @@ import type { ContextCapsuleBuildInput } from "./context-runtime-types";
5
5
 
6
6
  import { isValidLanguageHint } from "../config/types";
7
7
  import { normalizeTag, validateTag } from "../core/tags";
8
+ import {
9
+ metadataPredicateSchema,
10
+ normalizeMetadataPredicate,
11
+ } from "../core/typed-metadata";
8
12
  import { resolveTemporalRange } from "../pipeline/temporal";
9
13
  import { buildUri, parseUri } from "./constants";
10
14
  import { ContextRuntimeError } from "./context-runtime-types";
@@ -355,8 +359,21 @@ export const normalizeContextBuildInput = (
355
359
  "Context author or language filter is invalid"
356
360
  );
357
361
  }
362
+ const parsedFilter =
363
+ input.filter === undefined
364
+ ? undefined
365
+ : metadataPredicateSchema.safeParse(input.filter);
366
+ if (parsedFilter && !parsedFilter.success) {
367
+ throw new ContextRuntimeError(
368
+ "invalid_filter",
369
+ `filter: ${parsedFilter.error.message}`
370
+ );
371
+ }
358
372
  return {
359
373
  ...input,
374
+ ...(parsedFilter?.success
375
+ ? { filter: normalizeMetadataPredicate(parsedFilter.data) }
376
+ : {}),
360
377
  goal,
361
378
  query,
362
379
  indexName,
@@ -3,6 +3,7 @@ import type { ContextCapsuleV1 } from "../core/context-capsule";
3
3
  import type { ContextEvidenceCompilerDeps } from "../core/context-evidence";
4
4
  import type { ContextVerifierDeps } from "../core/context-verifier";
5
5
  import type { RetrievalTraceSession } from "../core/retrieval-trace-session";
6
+ import type { MetadataPredicate } from "../core/typed-metadata";
6
7
  import type { EmbeddingPort, RerankPort } from "../llm/types";
7
8
  import type { RequestHydration } from "../pipeline/hydration";
8
9
  import type { ProjectAffinityScoringInput } from "../pipeline/project-affinity";
@@ -22,6 +23,7 @@ export interface ContextCapsuleBuildInput {
22
23
  tagsAll?: string[];
23
24
  tagsAny?: string[];
24
25
  categories?: string[];
26
+ filter?: MetadataPredicate;
25
27
  author?: string;
26
28
  lang?: string;
27
29
  intent?: string;