@gmickel/gno 1.18.0 → 1.20.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/README.md +14 -7
- package/assets/skill/SKILL.md +54 -12
- package/assets/skill/mcp-reference.md +7 -2
- package/assets/skill/recipes/citation-and-provenance.md +32 -9
- package/package.json +2 -1
- package/spec/AGENTS.md +83 -0
- package/spec/CLAUDE.md +83 -0
- package/spec/bench-fixture.schema.json +137 -0
- package/spec/cli.md +2919 -0
- package/spec/db/schema.sql +442 -0
- package/spec/evals-agentic.md +592 -0
- package/spec/evals.md +1106 -0
- package/spec/mcp.md +2279 -0
- package/spec/output-schemas/activation-verification.schema.json +515 -0
- package/spec/output-schemas/ask.schema.json +564 -0
- package/spec/output-schemas/backlinks.schema.json +131 -0
- package/spec/output-schemas/bench-result.schema.json +120 -0
- package/spec/output-schemas/capture-receipt.schema.json +143 -0
- package/spec/output-schemas/claim-verification.schema.json +291 -0
- package/spec/output-schemas/collection-list.schema.json +45 -0
- package/spec/output-schemas/context-capsule-v1.schema.json +726 -0
- package/spec/output-schemas/context-capsule-verification.schema.json +1338 -0
- package/spec/output-schemas/context-list.schema.json +21 -0
- package/spec/output-schemas/doctor.schema.json +313 -0
- package/spec/output-schemas/error.schema.json +30 -0
- package/spec/output-schemas/expansion.schema.json +37 -0
- package/spec/output-schemas/get.schema.json +140 -0
- package/spec/output-schemas/graph-query.schema.json +99 -0
- package/spec/output-schemas/graph.schema.json +371 -0
- package/spec/output-schemas/links-list.schema.json +186 -0
- package/spec/output-schemas/mcp-add-collection-result.schema.json +23 -0
- package/spec/output-schemas/mcp-capture-result.schema.json +152 -0
- package/spec/output-schemas/mcp-http-error.schema.json +30 -0
- package/spec/output-schemas/mcp-job-list.schema.json +58 -0
- package/spec/output-schemas/mcp-job-status.schema.json +224 -0
- package/spec/output-schemas/mcp-remove-result.schema.json +39 -0
- package/spec/output-schemas/mcp-sync-result.schema.json +41 -0
- package/spec/output-schemas/mcp-tag-result.schema.json +33 -0
- package/spec/output-schemas/models-list.schema.json +93 -0
- package/spec/output-schemas/multi-get.schema.json +103 -0
- package/spec/output-schemas/process-status.schema.json +119 -0
- package/spec/output-schemas/query-diagnose.schema.json +123 -0
- package/spec/output-schemas/resident-status.schema.json +154 -0
- package/spec/output-schemas/retrieval-trace-common.schema.json +492 -0
- package/spec/output-schemas/retrieval-trace-delete.schema.json +16 -0
- package/spec/output-schemas/retrieval-trace-export.schema.json +61 -0
- package/spec/output-schemas/retrieval-trace-filters.schema.json +139 -0
- package/spec/output-schemas/retrieval-trace-judgment.schema.json +15 -0
- package/spec/output-schemas/retrieval-trace-list.schema.json +18 -0
- package/spec/output-schemas/retrieval-trace-payloads.schema.json +178 -0
- package/spec/output-schemas/retrieval-trace-purge.schema.json +31 -0
- package/spec/output-schemas/retrieval-trace-qrels.schema.json +303 -0
- package/spec/output-schemas/retrieval-trace-replay.schema.json +286 -0
- package/spec/output-schemas/retrieval-trace-show.schema.json +69 -0
- package/spec/output-schemas/retrieval-trace-summary.schema.json +65 -0
- package/spec/output-schemas/search-result.schema.json +154 -0
- package/spec/output-schemas/search-results.schema.json +338 -0
- package/spec/output-schemas/similar.schema.json +84 -0
- package/spec/output-schemas/status.schema.json +676 -0
- package/spec/output-schemas/tags-list.schema.json +48 -0
- package/src/app/context-runtime-contract.ts +10 -5
- package/src/app/context-runtime-input.ts +29 -1
- package/src/app/context-runtime-types.ts +7 -0
- package/src/app/context-runtime.ts +20 -2
- package/src/app/context-surface.ts +4 -0
- package/src/app/verified-ask.ts +291 -0
- package/src/cli/commands/ask-format.ts +255 -0
- package/src/cli/commands/ask.ts +144 -183
- package/src/cli/commands/context-build.ts +56 -9
- package/src/cli/commands/get.ts +64 -3
- package/src/cli/commands/query.ts +62 -23
- package/src/cli/commands/replay.ts +140 -0
- package/src/cli/commands/search.ts +48 -3
- package/src/cli/commands/shared.ts +3 -1
- package/src/cli/commands/trace.ts +200 -0
- package/src/cli/commands/vsearch.ts +75 -53
- package/src/cli/program.ts +287 -1
- package/src/config/index.ts +9 -0
- package/src/config/retrieval-traces.ts +56 -0
- package/src/config/types.ts +4 -0
- package/src/core/context-budget.ts +6 -0
- package/src/core/context-capsule-retrieval-schema.ts +4 -0
- package/src/core/context-capsule-schema.ts +17 -0
- package/src/core/context-capsule-validation.ts +3 -2
- package/src/core/context-capsule.ts +18 -0
- package/src/core/context-compiler.ts +44 -25
- package/src/core/context-evidence.ts +6 -0
- package/src/core/retrieval-qrels.ts +405 -0
- package/src/core/retrieval-replay-candidate.ts +368 -0
- package/src/core/retrieval-replay-types.ts +109 -0
- package/src/core/retrieval-replay-validation.ts +89 -0
- package/src/core/retrieval-replay.ts +441 -0
- package/src/core/retrieval-trace-evidence-origin.ts +178 -0
- package/src/core/retrieval-trace-export.ts +113 -0
- package/src/core/retrieval-trace-filter-normalization.ts +27 -0
- package/src/core/retrieval-trace-filters.ts +19 -0
- package/src/core/retrieval-trace-management-helpers.ts +247 -0
- package/src/core/retrieval-trace-management-types.ts +132 -0
- package/src/core/retrieval-trace-management.ts +422 -0
- package/src/core/retrieval-trace-request.ts +141 -0
- package/src/core/retrieval-trace-session.ts +507 -0
- package/src/core/retrieval-trace.ts +472 -0
- package/src/llm/errors.ts +10 -1
- package/src/llm/httpGeneration.ts +11 -1
- package/src/llm/nodeLlamaCpp/generation.ts +54 -10
- package/src/llm/types.ts +6 -0
- package/src/mcp/tools/ask.ts +228 -0
- package/src/mcp/tools/context.ts +87 -15
- package/src/mcp/tools/get.ts +35 -1
- package/src/mcp/tools/index.ts +83 -0
- package/src/mcp/tools/query.ts +95 -64
- package/src/mcp/tools/search.ts +36 -13
- package/src/mcp/tools/trace.ts +143 -0
- package/src/mcp/tools/vsearch.ts +71 -38
- package/src/pipeline/answer.ts +167 -26
- package/src/pipeline/claim-verification-schema.ts +235 -0
- package/src/pipeline/claim-verification.ts +487 -0
- package/src/pipeline/claim-verifier.ts +474 -0
- package/src/pipeline/graph-retrieval.ts +15 -1
- package/src/pipeline/hybrid.ts +151 -43
- package/src/pipeline/search.ts +36 -3
- package/src/pipeline/trace-metadata.ts +47 -0
- package/src/pipeline/types.ts +68 -0
- package/src/pipeline/vsearch.ts +101 -38
- package/src/sdk/client.ts +415 -73
- package/src/sdk/documents.ts +48 -1
- package/src/sdk/index.ts +17 -0
- package/src/sdk/types.ts +28 -0
- package/src/serve/context-capsule.ts +67 -8
- package/src/serve/public/app.tsx +12 -1
- package/src/serve/public/components/AskVerificationPanel.tsx +189 -0
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/lib/workspace-tabs.ts +2 -0
- package/src/serve/public/pages/Ask.tsx +42 -4
- package/src/serve/public/pages/Dashboard.tsx +10 -0
- package/src/serve/public/pages/TraceHistory.tsx +478 -0
- package/src/serve/public/pages/trace-history-detail.tsx +224 -0
- package/src/serve/retrieval-trace.ts +28 -0
- package/src/serve/routes/api.ts +508 -68
- package/src/serve/routes/traces.ts +156 -0
- package/src/serve/server.ts +87 -2
- package/src/store/index.ts +31 -0
- package/src/store/migrations/014-retrieval-traces.ts +303 -0
- package/src/store/migrations/index.ts +2 -0
- package/src/store/retrieval-trace-codec.ts +384 -0
- package/src/store/sqlite/adapter.ts +153 -1
- package/src/store/sqlite/retrieval-trace-management-store.ts +341 -0
- package/src/store/sqlite/retrieval-trace-retention.ts +349 -0
- package/src/store/sqlite/retrieval-trace-rows.ts +267 -0
- package/src/store/sqlite/retrieval-trace-store.ts +515 -0
- package/src/store/types.ts +297 -0
- package/src/store/vector/sqlite-vec.ts +76 -1
- package/src/store/vector/types.ts +1 -1
package/src/pipeline/hybrid.ts
CHANGED
|
@@ -55,9 +55,10 @@ import {
|
|
|
55
55
|
shouldSortByRecency,
|
|
56
56
|
} from "./temporal";
|
|
57
57
|
import {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
} from "./
|
|
58
|
+
attachSearchResultPlannerMetadata,
|
|
59
|
+
attachSearchResultsTraceMetadata,
|
|
60
|
+
} from "./trace-metadata";
|
|
61
|
+
import { DEFAULT_PIPELINE_CONFIG } from "./types";
|
|
61
62
|
|
|
62
63
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
63
64
|
// Dependencies
|
|
@@ -121,11 +122,13 @@ async function checkBm25Strength(
|
|
|
121
122
|
until?: string;
|
|
122
123
|
categories?: string[];
|
|
123
124
|
author?: string;
|
|
125
|
+
relPathPrefix?: string;
|
|
124
126
|
}
|
|
125
127
|
): Promise<boolean> {
|
|
126
128
|
const result = await store.searchFts(query, {
|
|
127
129
|
limit: 5,
|
|
128
130
|
collection: options?.collection,
|
|
131
|
+
relPathPrefix: options?.relPathPrefix,
|
|
129
132
|
language: options?.lang,
|
|
130
133
|
tagsAll: options?.tagsAll,
|
|
131
134
|
tagsAny: options?.tagsAny,
|
|
@@ -179,11 +182,13 @@ async function searchFtsChunks(
|
|
|
179
182
|
until?: string;
|
|
180
183
|
categories?: string[];
|
|
181
184
|
author?: string;
|
|
185
|
+
relPathPrefix?: string;
|
|
182
186
|
}
|
|
183
187
|
): Promise<FtsChunksResult> {
|
|
184
188
|
const result = await store.searchFts(query, {
|
|
185
189
|
limit: options.limit,
|
|
186
190
|
collection: options.collection,
|
|
191
|
+
relPathPrefix: options.relPathPrefix,
|
|
187
192
|
language: options.lang,
|
|
188
193
|
tagsAll: options.tagsAll,
|
|
189
194
|
tagsAny: options.tagsAny,
|
|
@@ -216,7 +221,11 @@ async function searchVectorChunks(
|
|
|
216
221
|
vectorIndex: VectorIndexPort,
|
|
217
222
|
embedPort: EmbeddingPort,
|
|
218
223
|
query: string,
|
|
219
|
-
options: {
|
|
224
|
+
options: {
|
|
225
|
+
limit: number;
|
|
226
|
+
minScore?: number;
|
|
227
|
+
allowedMirrorHashes?: string[];
|
|
228
|
+
}
|
|
220
229
|
): Promise<ChunkId[]> {
|
|
221
230
|
if (!vectorIndex.searchAvailable) {
|
|
222
231
|
return [];
|
|
@@ -234,7 +243,10 @@ async function searchVectorChunks(
|
|
|
234
243
|
const searchResult = await vectorIndex.searchNearest(
|
|
235
244
|
queryEmbedding,
|
|
236
245
|
options.limit,
|
|
237
|
-
{
|
|
246
|
+
{
|
|
247
|
+
minScore: options.minScore,
|
|
248
|
+
allowedMirrorHashes: options.allowedMirrorHashes,
|
|
249
|
+
}
|
|
238
250
|
);
|
|
239
251
|
|
|
240
252
|
if (!searchResult.ok) {
|
|
@@ -381,6 +393,7 @@ export async function searchHybrid(
|
|
|
381
393
|
until: temporalRange.until,
|
|
382
394
|
categories: options.categories,
|
|
383
395
|
author: options.author,
|
|
396
|
+
relPathPrefix: options.retrievalScope?.relPathPrefix,
|
|
384
397
|
});
|
|
385
398
|
|
|
386
399
|
if (hasStrongSignal) {
|
|
@@ -397,6 +410,8 @@ export async function searchHybrid(
|
|
|
397
410
|
});
|
|
398
411
|
if (expandResult.ok) {
|
|
399
412
|
expansion = expandResult.value;
|
|
413
|
+
} else {
|
|
414
|
+
counters.fallbackEvents.push("expansion_error");
|
|
400
415
|
}
|
|
401
416
|
}
|
|
402
417
|
}
|
|
@@ -428,6 +443,7 @@ export async function searchHybrid(
|
|
|
428
443
|
until: temporalRange.until,
|
|
429
444
|
categories: options.categories,
|
|
430
445
|
author: options.author,
|
|
446
|
+
relPathPrefix: options.retrievalScope?.relPathPrefix,
|
|
431
447
|
});
|
|
432
448
|
|
|
433
449
|
// Propagate FTS syntax errors as INVALID_INPUT
|
|
@@ -462,6 +478,7 @@ export async function searchHybrid(
|
|
|
462
478
|
until: temporalRange.until,
|
|
463
479
|
categories: options.categories,
|
|
464
480
|
author: options.author,
|
|
481
|
+
relPathPrefix: options.retrievalScope?.relPathPrefix,
|
|
465
482
|
})
|
|
466
483
|
)
|
|
467
484
|
);
|
|
@@ -509,6 +526,7 @@ export async function searchHybrid(
|
|
|
509
526
|
query,
|
|
510
527
|
{
|
|
511
528
|
limit: limit * 2 * retrievalMultiplier,
|
|
529
|
+
allowedMirrorHashes: options.retrievalScope?.allowedMirrorHashes,
|
|
512
530
|
}
|
|
513
531
|
);
|
|
514
532
|
|
|
@@ -552,7 +570,10 @@ export async function searchHybrid(
|
|
|
552
570
|
|
|
553
571
|
const searchResult = await vectorIndex.searchNearest(
|
|
554
572
|
new Float32Array(embedding),
|
|
555
|
-
variant.limit
|
|
573
|
+
variant.limit,
|
|
574
|
+
{
|
|
575
|
+
allowedMirrorHashes: options.retrievalScope?.allowedMirrorHashes,
|
|
576
|
+
}
|
|
556
577
|
);
|
|
557
578
|
if (!searchResult.ok || searchResult.value.length === 0) {
|
|
558
579
|
continue;
|
|
@@ -615,6 +636,7 @@ export async function searchHybrid(
|
|
|
615
636
|
limit,
|
|
616
637
|
candidateLimit,
|
|
617
638
|
disabled: !options.graph || options.noGraph,
|
|
639
|
+
relPathPrefix: options.retrievalScope?.relPathPrefix,
|
|
618
640
|
lang: options.lang,
|
|
619
641
|
tagsAll: options.tagsAll,
|
|
620
642
|
tagsAny: options.tagsAny,
|
|
@@ -735,6 +757,14 @@ export async function searchHybrid(
|
|
|
735
757
|
const matchesMetadataFilters = (
|
|
736
758
|
doc: (typeof docsResult.value)[number]
|
|
737
759
|
): boolean => {
|
|
760
|
+
const relPathPrefix = options.retrievalScope?.relPathPrefix;
|
|
761
|
+
if (
|
|
762
|
+
relPathPrefix !== undefined &&
|
|
763
|
+
doc.relPath !== relPathPrefix &&
|
|
764
|
+
!doc.relPath.startsWith(`${relPathPrefix}/`)
|
|
765
|
+
) {
|
|
766
|
+
return false;
|
|
767
|
+
}
|
|
738
768
|
if (!isWithinTemporalRange(doc.sourceMtime, temporalRange)) {
|
|
739
769
|
return false;
|
|
740
770
|
}
|
|
@@ -923,42 +953,51 @@ export async function searchHybrid(
|
|
|
923
953
|
if (!docidMap.has(docidKey)) docidMap.set(docidKey, doc.docid);
|
|
924
954
|
const collectionPath = collectionPaths.get(doc.collection);
|
|
925
955
|
seenDocids.add(doc.docid);
|
|
926
|
-
results.push(
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
956
|
+
results.push(
|
|
957
|
+
attachSearchResultPlannerMetadata(
|
|
958
|
+
{
|
|
959
|
+
docid: doc.docid,
|
|
960
|
+
score: candidate.blendedScore,
|
|
961
|
+
uri: doc.uri,
|
|
962
|
+
title: doc.title ?? undefined,
|
|
963
|
+
contentType: doc.contentType ?? undefined,
|
|
964
|
+
categories: doc.categories ?? undefined,
|
|
965
|
+
line: snippetChunk.startLine,
|
|
966
|
+
snippet,
|
|
967
|
+
snippetLanguage: chunk.language ?? undefined,
|
|
968
|
+
snippetRange,
|
|
969
|
+
source: {
|
|
970
|
+
relPath: doc.relPath,
|
|
971
|
+
absPath: collectionPath
|
|
972
|
+
? `${collectionPath}/${doc.relPath}`
|
|
973
|
+
: undefined,
|
|
974
|
+
mime: doc.sourceMime,
|
|
975
|
+
ext: doc.sourceExt,
|
|
976
|
+
modifiedAt: doc.sourceMtime,
|
|
977
|
+
documentDate: doc.frontmatterDate ?? undefined,
|
|
978
|
+
sizeBytes: doc.sourceSize,
|
|
979
|
+
sourceHash: doc.sourceHash,
|
|
980
|
+
},
|
|
981
|
+
conversion: {
|
|
982
|
+
mirrorHash: candidate.mirrorHash,
|
|
983
|
+
converterId: doc.converterId ?? undefined,
|
|
984
|
+
converterVersion: doc.converterVersion ?? undefined,
|
|
985
|
+
},
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
retrievalRank: candidateIndex + 1,
|
|
989
|
+
mirrorHash: candidate.mirrorHash,
|
|
990
|
+
seq: snippetChunk.seq,
|
|
991
|
+
sources: [...candidate.sources].sort(),
|
|
992
|
+
graphExpanded: candidate.sources.includes("graph"),
|
|
993
|
+
startLine: snippetChunk.startLine,
|
|
994
|
+
endLine: snippetChunk.endLine,
|
|
995
|
+
passageHash: new Bun.CryptoHasher("sha256")
|
|
996
|
+
.update(snippetChunk.text)
|
|
997
|
+
.digest("hex"),
|
|
998
|
+
}
|
|
999
|
+
)
|
|
1000
|
+
);
|
|
962
1001
|
}
|
|
963
1002
|
}
|
|
964
1003
|
timings.assemblyMs = performance.now() - assemblyStartedAt;
|
|
@@ -1002,7 +1041,7 @@ export async function searchHybrid(
|
|
|
1002
1041
|
const finalResults = results.slice(0, limit);
|
|
1003
1042
|
await attachSearchResultContexts(store, finalResults);
|
|
1004
1043
|
|
|
1005
|
-
|
|
1044
|
+
const output: SearchResults = {
|
|
1006
1045
|
results: finalResults,
|
|
1007
1046
|
meta: {
|
|
1008
1047
|
query,
|
|
@@ -1033,5 +1072,74 @@ export async function searchHybrid(
|
|
|
1033
1072
|
explain: explainData,
|
|
1034
1073
|
trace: diagnoseTrace,
|
|
1035
1074
|
},
|
|
1075
|
+
};
|
|
1076
|
+
const fallbackCodes = [...new Set(counters.fallbackEvents)].sort();
|
|
1077
|
+
const capabilityOutcomes = [
|
|
1078
|
+
{ capability: "lexical_search", status: "used" as const },
|
|
1079
|
+
vectorAvailable
|
|
1080
|
+
? fallbackCodes.includes("vector_embed_error")
|
|
1081
|
+
? {
|
|
1082
|
+
capability: "semantic_search",
|
|
1083
|
+
status: "failed" as const,
|
|
1084
|
+
reasonCode: "vector_embed_error",
|
|
1085
|
+
}
|
|
1086
|
+
: { capability: "semantic_search", status: "used" as const }
|
|
1087
|
+
: {
|
|
1088
|
+
capability: "semantic_search",
|
|
1089
|
+
status: "unavailable" as const,
|
|
1090
|
+
reasonCode: "vector_unavailable",
|
|
1091
|
+
},
|
|
1092
|
+
expansion !== null
|
|
1093
|
+
? { capability: "query_expansion", status: "used" as const }
|
|
1094
|
+
: {
|
|
1095
|
+
capability: "query_expansion",
|
|
1096
|
+
status:
|
|
1097
|
+
expansionStatus === "attempted"
|
|
1098
|
+
? ("failed" as const)
|
|
1099
|
+
: ("unavailable" as const),
|
|
1100
|
+
reasonCode:
|
|
1101
|
+
expansionStatus === "attempted"
|
|
1102
|
+
? "expansion_error"
|
|
1103
|
+
: expansionStatus === "skipped_strong"
|
|
1104
|
+
? "expansion_skipped_strong"
|
|
1105
|
+
: "expansion_disabled",
|
|
1106
|
+
},
|
|
1107
|
+
rerankResult.reranked
|
|
1108
|
+
? { capability: "reranking", status: "used" as const }
|
|
1109
|
+
: {
|
|
1110
|
+
capability: "reranking",
|
|
1111
|
+
status:
|
|
1112
|
+
rerankResult.fallbackReason === "error"
|
|
1113
|
+
? ("failed" as const)
|
|
1114
|
+
: ("unavailable" as const),
|
|
1115
|
+
reasonCode:
|
|
1116
|
+
rerankResult.fallbackReason === "error"
|
|
1117
|
+
? "rerank_error"
|
|
1118
|
+
: "rerank_disabled",
|
|
1119
|
+
},
|
|
1120
|
+
graphExpansion.meta.enabled
|
|
1121
|
+
? { capability: "graph_expansion", status: "used" as const }
|
|
1122
|
+
: {
|
|
1123
|
+
capability: "graph_expansion",
|
|
1124
|
+
status: "unavailable" as const,
|
|
1125
|
+
reasonCode:
|
|
1126
|
+
graphExpansion.meta.fallbackReasons[0] ?? "graph_disabled",
|
|
1127
|
+
},
|
|
1128
|
+
];
|
|
1129
|
+
attachSearchResultsTraceMetadata(output, {
|
|
1130
|
+
capabilityOutcomes,
|
|
1131
|
+
fallbackCodes,
|
|
1036
1132
|
});
|
|
1133
|
+
const traceResult = await options.traceSession?.recordRetrieval(
|
|
1134
|
+
output,
|
|
1135
|
+
timings.totalMs
|
|
1136
|
+
);
|
|
1137
|
+
if (traceResult && !traceResult.ok) {
|
|
1138
|
+
return err(
|
|
1139
|
+
"QUERY_FAILED",
|
|
1140
|
+
`Trace recording failed: ${traceResult.error.message}`,
|
|
1141
|
+
traceResult.error.cause
|
|
1142
|
+
);
|
|
1143
|
+
}
|
|
1144
|
+
return ok(output);
|
|
1037
1145
|
}
|
package/src/pipeline/search.ts
CHANGED
|
@@ -27,6 +27,8 @@ import {
|
|
|
27
27
|
resolveTemporalRange,
|
|
28
28
|
shouldSortByRecency,
|
|
29
29
|
} from "./temporal";
|
|
30
|
+
import { attachSearchResultPlannerMetadata } from "./trace-metadata";
|
|
31
|
+
import { SEARCH_RESULT_PLANNER_METADATA } from "./types";
|
|
30
32
|
|
|
31
33
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
32
34
|
// Score Normalization
|
|
@@ -113,7 +115,7 @@ function buildSearchResult(ctx: BuildResultContext): SearchResult {
|
|
|
113
115
|
: undefined;
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
|
|
118
|
+
const result: SearchResult = {
|
|
117
119
|
docid: fts.docid ?? "",
|
|
118
120
|
score: fts.score, // Raw score, normalized later as batch
|
|
119
121
|
uri: fts.uri ?? "",
|
|
@@ -127,6 +129,19 @@ function buildSearchResult(ctx: BuildResultContext): SearchResult {
|
|
|
127
129
|
source,
|
|
128
130
|
conversion: fts.mirrorHash ? { mirrorHash: fts.mirrorHash } : undefined,
|
|
129
131
|
};
|
|
132
|
+
if (!(chunk && fts.mirrorHash)) return result;
|
|
133
|
+
return attachSearchResultPlannerMetadata(result, {
|
|
134
|
+
retrievalRank: 0,
|
|
135
|
+
mirrorHash: fts.mirrorHash,
|
|
136
|
+
seq: chunk.seq,
|
|
137
|
+
sources: ["bm25"],
|
|
138
|
+
graphExpanded: false,
|
|
139
|
+
startLine: chunk.startLine,
|
|
140
|
+
endLine: chunk.endLine,
|
|
141
|
+
passageHash: new Bun.CryptoHasher("sha256")
|
|
142
|
+
.update(chunk.text)
|
|
143
|
+
.digest("hex"),
|
|
144
|
+
});
|
|
130
145
|
}
|
|
131
146
|
|
|
132
147
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -142,6 +157,7 @@ export async function searchBm25(
|
|
|
142
157
|
query: string,
|
|
143
158
|
options: SearchOptions = {}
|
|
144
159
|
): Promise<ReturnType<typeof ok<SearchResults>>> {
|
|
160
|
+
const traceStartedAt = options.traceSession ? performance.now() : 0;
|
|
145
161
|
const limit = options.limit ?? 20;
|
|
146
162
|
const minScore = options.minScore ?? 0;
|
|
147
163
|
const recencySort = shouldSortByRecency(query);
|
|
@@ -161,6 +177,7 @@ export async function searchBm25(
|
|
|
161
177
|
const ftsResult = await store.searchFts(query, {
|
|
162
178
|
limit: retrievalLimit,
|
|
163
179
|
collection: options.collection,
|
|
180
|
+
relPathPrefix: options.retrievalScope?.relPathPrefix,
|
|
164
181
|
language: options.lang,
|
|
165
182
|
snippet: !(options.full || options.lineNumbers),
|
|
166
183
|
tagsAll: options.tagsAll,
|
|
@@ -331,9 +348,13 @@ export async function searchBm25(
|
|
|
331
348
|
}
|
|
332
349
|
|
|
333
350
|
const finalResults = filteredResults.slice(0, limit);
|
|
351
|
+
for (const [index, result] of finalResults.entries()) {
|
|
352
|
+
const metadata = result[SEARCH_RESULT_PLANNER_METADATA];
|
|
353
|
+
if (metadata) metadata.retrievalRank = index + 1;
|
|
354
|
+
}
|
|
334
355
|
await attachSearchResultContexts(store, finalResults);
|
|
335
356
|
|
|
336
|
-
|
|
357
|
+
const output: SearchResults = {
|
|
337
358
|
results: finalResults,
|
|
338
359
|
meta: {
|
|
339
360
|
query,
|
|
@@ -349,5 +370,17 @@ export async function searchBm25(
|
|
|
349
370
|
author: options.author,
|
|
350
371
|
queryLanguage,
|
|
351
372
|
},
|
|
352
|
-
}
|
|
373
|
+
};
|
|
374
|
+
const traceResult = await options.traceSession?.recordRetrieval(
|
|
375
|
+
output,
|
|
376
|
+
performance.now() - traceStartedAt
|
|
377
|
+
);
|
|
378
|
+
if (traceResult && !traceResult.ok) {
|
|
379
|
+
return err(
|
|
380
|
+
"QUERY_FAILED",
|
|
381
|
+
`Trace recording failed: ${traceResult.error.message}`,
|
|
382
|
+
traceResult.error.cause
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
return ok(output);
|
|
353
386
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Non-canonical retrieval metadata attached without changing public payloads. */
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
Citation,
|
|
5
|
+
CitationTraceMetadata,
|
|
6
|
+
SearchResult,
|
|
7
|
+
SearchResultPlannerMetadata,
|
|
8
|
+
SearchResults,
|
|
9
|
+
SearchResultsTraceMetadata,
|
|
10
|
+
} from "./types";
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
CITATION_TRACE_METADATA,
|
|
14
|
+
SEARCH_RESULT_PLANNER_METADATA,
|
|
15
|
+
SEARCH_RESULTS_TRACE_METADATA,
|
|
16
|
+
} from "./types";
|
|
17
|
+
|
|
18
|
+
const attachHiddenMetadata = <Value extends object, Metadata>(
|
|
19
|
+
value: Value,
|
|
20
|
+
key: symbol,
|
|
21
|
+
metadata: Metadata
|
|
22
|
+
): Value => {
|
|
23
|
+
Object.defineProperty(value, key, {
|
|
24
|
+
configurable: false,
|
|
25
|
+
enumerable: false,
|
|
26
|
+
value: metadata,
|
|
27
|
+
writable: false,
|
|
28
|
+
});
|
|
29
|
+
return value;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const attachSearchResultPlannerMetadata = <Result extends SearchResult>(
|
|
33
|
+
result: Result,
|
|
34
|
+
metadata: SearchResultPlannerMetadata
|
|
35
|
+
): Result =>
|
|
36
|
+
attachHiddenMetadata(result, SEARCH_RESULT_PLANNER_METADATA, metadata);
|
|
37
|
+
|
|
38
|
+
export const attachCitationTraceMetadata = <Result extends Citation>(
|
|
39
|
+
citation: Result,
|
|
40
|
+
metadata: CitationTraceMetadata
|
|
41
|
+
): Result => attachHiddenMetadata(citation, CITATION_TRACE_METADATA, metadata);
|
|
42
|
+
|
|
43
|
+
export const attachSearchResultsTraceMetadata = <Result extends SearchResults>(
|
|
44
|
+
results: Result,
|
|
45
|
+
metadata: SearchResultsTraceMetadata
|
|
46
|
+
): Result =>
|
|
47
|
+
attachHiddenMetadata(results, SEARCH_RESULTS_TRACE_METADATA, metadata);
|
package/src/pipeline/types.ts
CHANGED
|
@@ -5,7 +5,14 @@
|
|
|
5
5
|
* @module src/pipeline/types
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type {
|
|
9
|
+
ContextCapsuleV1,
|
|
10
|
+
ContextCapsuleVerification,
|
|
11
|
+
} from "../core/context-capsule";
|
|
12
|
+
import type { RetrievalTraceSession } from "../core/retrieval-trace-session";
|
|
8
13
|
import type { StoreResult } from "../store/types";
|
|
14
|
+
import type { ClaimVerificationResult } from "./claim-verification";
|
|
15
|
+
import type { SemanticVerificationCapability } from "./claim-verifier";
|
|
9
16
|
|
|
10
17
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
11
18
|
// Search Result Types
|
|
@@ -48,6 +55,11 @@ export interface SearchResultPlannerMetadata {
|
|
|
48
55
|
seq: number;
|
|
49
56
|
sources: FusionSource[];
|
|
50
57
|
graphExpanded: boolean;
|
|
58
|
+
/** Exact canonical chunk coordinates, retained even for full-content output. */
|
|
59
|
+
startLine?: number;
|
|
60
|
+
endLine?: number;
|
|
61
|
+
/** SHA-256 of the complete canonical chunk lines. */
|
|
62
|
+
passageHash?: string;
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
/** Single search result matching output schema */
|
|
@@ -122,10 +134,26 @@ export interface SearchMeta {
|
|
|
122
134
|
trace?: QueryDiagnoseTrace;
|
|
123
135
|
}
|
|
124
136
|
|
|
137
|
+
export const SEARCH_RESULTS_TRACE_METADATA = Symbol(
|
|
138
|
+
"gno.searchResultsTraceMetadata"
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
export interface SearchCapabilityOutcome {
|
|
142
|
+
capability: string;
|
|
143
|
+
status: "attempted" | "used" | "unavailable" | "failed";
|
|
144
|
+
reasonCode?: string;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface SearchResultsTraceMetadata {
|
|
148
|
+
capabilityOutcomes: SearchCapabilityOutcome[];
|
|
149
|
+
fallbackCodes: string[];
|
|
150
|
+
}
|
|
151
|
+
|
|
125
152
|
/** Complete search results wrapper */
|
|
126
153
|
export interface SearchResults {
|
|
127
154
|
results: SearchResult[];
|
|
128
155
|
meta: SearchMeta;
|
|
156
|
+
[SEARCH_RESULTS_TRACE_METADATA]?: SearchResultsTraceMetadata;
|
|
129
157
|
}
|
|
130
158
|
|
|
131
159
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -134,12 +162,19 @@ export interface SearchResults {
|
|
|
134
162
|
|
|
135
163
|
/** Common options for all search commands */
|
|
136
164
|
export interface SearchOptions {
|
|
165
|
+
/** Internal receipt seam; never serialized or included in public schemas. */
|
|
166
|
+
traceSession?: RetrievalTraceSession;
|
|
137
167
|
/** Max results */
|
|
138
168
|
limit?: number;
|
|
139
169
|
/** Min score threshold (0-1) */
|
|
140
170
|
minScore?: number;
|
|
141
171
|
/** Filter by collection */
|
|
142
172
|
collection?: string;
|
|
173
|
+
/** Internal exact corpus scope used by deterministic retrieval replay. */
|
|
174
|
+
retrievalScope?: {
|
|
175
|
+
relPathPrefix?: string;
|
|
176
|
+
allowedMirrorHashes: string[];
|
|
177
|
+
};
|
|
143
178
|
/** Language filter/hint (BCP-47) */
|
|
144
179
|
lang?: string;
|
|
145
180
|
/** Include full content instead of snippet */
|
|
@@ -210,6 +245,12 @@ export type AskOptions = HybridSearchOptions & {
|
|
|
210
245
|
noAnswer?: boolean;
|
|
211
246
|
/** Max tokens for answer */
|
|
212
247
|
maxAnswerTokens?: number;
|
|
248
|
+
/** Verify generated claims against a closed Context Capsule. */
|
|
249
|
+
verify?: boolean;
|
|
250
|
+
/** Global Context Capsule budget used by verified Ask. */
|
|
251
|
+
contextBudgetTokens?: number;
|
|
252
|
+
/** Optional explicit byte budget used by verified Ask. */
|
|
253
|
+
contextBudgetBytes?: number;
|
|
213
254
|
};
|
|
214
255
|
|
|
215
256
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -357,11 +398,26 @@ export const DEFAULT_PIPELINE_CONFIG: PipelineConfig = {
|
|
|
357
398
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
358
399
|
|
|
359
400
|
/** Citation reference */
|
|
401
|
+
export const CITATION_TRACE_METADATA = Symbol("gno.citationTraceMetadata");
|
|
402
|
+
|
|
403
|
+
export interface CitationTraceMetadata {
|
|
404
|
+
sourceHash: string;
|
|
405
|
+
mirrorHash: string;
|
|
406
|
+
passageHash: string;
|
|
407
|
+
seq?: number;
|
|
408
|
+
rank: number;
|
|
409
|
+
plannerRank?: number;
|
|
410
|
+
sources?: FusionSource[];
|
|
411
|
+
graphExpanded?: boolean;
|
|
412
|
+
}
|
|
413
|
+
|
|
360
414
|
export interface Citation {
|
|
415
|
+
evidenceId?: string;
|
|
361
416
|
docid: string;
|
|
362
417
|
uri: string;
|
|
363
418
|
startLine?: number;
|
|
364
419
|
endLine?: number;
|
|
420
|
+
[CITATION_TRACE_METADATA]?: CitationTraceMetadata;
|
|
365
421
|
}
|
|
366
422
|
|
|
367
423
|
/** Source selection entry for answer-generation explain */
|
|
@@ -395,6 +451,17 @@ export interface AskMeta {
|
|
|
395
451
|
answerGenerated?: boolean;
|
|
396
452
|
totalResults?: number;
|
|
397
453
|
answerContext?: AnswerContextExplain;
|
|
454
|
+
verificationRequested?: boolean;
|
|
455
|
+
abstained?: boolean;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export interface AskVerification {
|
|
459
|
+
schemaVersion: "1.0";
|
|
460
|
+
mode: "closed_capsule";
|
|
461
|
+
capsule: ContextCapsuleV1;
|
|
462
|
+
freshness: ContextCapsuleVerification;
|
|
463
|
+
claims: ClaimVerificationResult;
|
|
464
|
+
semantic: SemanticVerificationCapability;
|
|
398
465
|
}
|
|
399
466
|
|
|
400
467
|
/** Ask command result */
|
|
@@ -406,6 +473,7 @@ export interface AskResult {
|
|
|
406
473
|
citations?: Citation[];
|
|
407
474
|
results: SearchResult[];
|
|
408
475
|
meta: AskMeta;
|
|
476
|
+
verification?: AskVerification;
|
|
409
477
|
}
|
|
410
478
|
|
|
411
479
|
// ─────────────────────────────────────────────────────────────────────────────
|