@gmickel/gno 1.17.0 → 1.19.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 (167) hide show
  1. package/README.md +18 -4
  2. package/assets/skill/SKILL.md +44 -1
  3. package/assets/skill/mcp-reference.md +21 -0
  4. package/package.json +3 -2
  5. package/spec/AGENTS.md +83 -0
  6. package/spec/CLAUDE.md +83 -0
  7. package/spec/bench-fixture.schema.json +137 -0
  8. package/spec/cli.md +2894 -0
  9. package/spec/db/schema.sql +442 -0
  10. package/spec/evals-agentic.md +510 -0
  11. package/spec/evals.md +1106 -0
  12. package/spec/mcp.md +2229 -0
  13. package/spec/output-schemas/activation-verification.schema.json +515 -0
  14. package/spec/output-schemas/ask.schema.json +366 -0
  15. package/spec/output-schemas/backlinks.schema.json +131 -0
  16. package/spec/output-schemas/bench-result.schema.json +120 -0
  17. package/spec/output-schemas/capture-receipt.schema.json +143 -0
  18. package/spec/output-schemas/collection-list.schema.json +45 -0
  19. package/spec/output-schemas/context-capsule-v1.schema.json +691 -0
  20. package/spec/output-schemas/context-capsule-verification.schema.json +1338 -0
  21. package/spec/output-schemas/context-list.schema.json +21 -0
  22. package/spec/output-schemas/doctor.schema.json +313 -0
  23. package/spec/output-schemas/error.schema.json +30 -0
  24. package/spec/output-schemas/expansion.schema.json +37 -0
  25. package/spec/output-schemas/get.schema.json +140 -0
  26. package/spec/output-schemas/graph-query.schema.json +99 -0
  27. package/spec/output-schemas/graph.schema.json +371 -0
  28. package/spec/output-schemas/links-list.schema.json +186 -0
  29. package/spec/output-schemas/mcp-add-collection-result.schema.json +23 -0
  30. package/spec/output-schemas/mcp-capture-result.schema.json +152 -0
  31. package/spec/output-schemas/mcp-http-error.schema.json +30 -0
  32. package/spec/output-schemas/mcp-job-list.schema.json +58 -0
  33. package/spec/output-schemas/mcp-job-status.schema.json +224 -0
  34. package/spec/output-schemas/mcp-remove-result.schema.json +39 -0
  35. package/spec/output-schemas/mcp-sync-result.schema.json +41 -0
  36. package/spec/output-schemas/mcp-tag-result.schema.json +33 -0
  37. package/spec/output-schemas/models-list.schema.json +93 -0
  38. package/spec/output-schemas/multi-get.schema.json +103 -0
  39. package/spec/output-schemas/process-status.schema.json +119 -0
  40. package/spec/output-schemas/query-diagnose.schema.json +123 -0
  41. package/spec/output-schemas/resident-status.schema.json +154 -0
  42. package/spec/output-schemas/retrieval-trace-common.schema.json +492 -0
  43. package/spec/output-schemas/retrieval-trace-delete.schema.json +16 -0
  44. package/spec/output-schemas/retrieval-trace-export.schema.json +61 -0
  45. package/spec/output-schemas/retrieval-trace-filters.schema.json +139 -0
  46. package/spec/output-schemas/retrieval-trace-judgment.schema.json +15 -0
  47. package/spec/output-schemas/retrieval-trace-list.schema.json +18 -0
  48. package/spec/output-schemas/retrieval-trace-payloads.schema.json +178 -0
  49. package/spec/output-schemas/retrieval-trace-purge.schema.json +31 -0
  50. package/spec/output-schemas/retrieval-trace-qrels.schema.json +303 -0
  51. package/spec/output-schemas/retrieval-trace-replay.schema.json +286 -0
  52. package/spec/output-schemas/retrieval-trace-show.schema.json +69 -0
  53. package/spec/output-schemas/retrieval-trace-summary.schema.json +65 -0
  54. package/spec/output-schemas/search-result.schema.json +154 -0
  55. package/spec/output-schemas/search-results.schema.json +338 -0
  56. package/spec/output-schemas/similar.schema.json +84 -0
  57. package/spec/output-schemas/status.schema.json +676 -0
  58. package/spec/output-schemas/tags-list.schema.json +48 -0
  59. package/src/app/context-runtime-types.ts +3 -0
  60. package/src/app/context-runtime.ts +15 -1
  61. package/src/cli/commands/ask.ts +106 -36
  62. package/src/cli/commands/context-build.ts +56 -9
  63. package/src/cli/commands/daemon.ts +69 -2
  64. package/src/cli/commands/get.ts +64 -3
  65. package/src/cli/commands/models/pull.ts +13 -3
  66. package/src/cli/commands/query.ts +62 -23
  67. package/src/cli/commands/replay.ts +140 -0
  68. package/src/cli/commands/search.ts +48 -3
  69. package/src/cli/commands/shared.ts +3 -1
  70. package/src/cli/commands/status.ts +2 -0
  71. package/src/cli/commands/trace.ts +200 -0
  72. package/src/cli/commands/vsearch.ts +75 -53
  73. package/src/cli/detach.ts +37 -20
  74. package/src/cli/program.ts +329 -27
  75. package/src/config/index.ts +12 -0
  76. package/src/config/retrieval-traces.ts +56 -0
  77. package/src/config/types.ts +41 -0
  78. package/src/core/context-compiler.ts +11 -4
  79. package/src/core/job-manager.ts +19 -0
  80. package/src/core/mutation-generations.ts +33 -0
  81. package/src/core/retrieval-qrels.ts +405 -0
  82. package/src/core/retrieval-replay-candidate.ts +368 -0
  83. package/src/core/retrieval-replay-types.ts +109 -0
  84. package/src/core/retrieval-replay-validation.ts +89 -0
  85. package/src/core/retrieval-replay.ts +441 -0
  86. package/src/core/retrieval-trace-evidence-origin.ts +175 -0
  87. package/src/core/retrieval-trace-export.ts +113 -0
  88. package/src/core/retrieval-trace-filter-normalization.ts +27 -0
  89. package/src/core/retrieval-trace-filters.ts +19 -0
  90. package/src/core/retrieval-trace-management-helpers.ts +247 -0
  91. package/src/core/retrieval-trace-management-types.ts +132 -0
  92. package/src/core/retrieval-trace-management.ts +422 -0
  93. package/src/core/retrieval-trace-request.ts +141 -0
  94. package/src/core/retrieval-trace-session.ts +494 -0
  95. package/src/core/retrieval-trace.ts +472 -0
  96. package/src/llm/cache.ts +13 -3
  97. package/src/llm/nodeLlamaCpp/adapter.ts +10 -1
  98. package/src/llm/nodeLlamaCpp/lifecycle.ts +71 -0
  99. package/src/mcp/context.ts +161 -0
  100. package/src/mcp/http-security.ts +477 -0
  101. package/src/mcp/http-session.ts +272 -0
  102. package/src/mcp/http-transport.ts +370 -0
  103. package/src/mcp/resources/index.ts +141 -134
  104. package/src/mcp/server.ts +19 -79
  105. package/src/mcp/tools/add-collection.ts +3 -1
  106. package/src/mcp/tools/capture.ts +3 -0
  107. package/src/mcp/tools/clear-collection-embeddings.ts +2 -0
  108. package/src/mcp/tools/context.ts +68 -16
  109. package/src/mcp/tools/embed.ts +62 -52
  110. package/src/mcp/tools/get.ts +35 -1
  111. package/src/mcp/tools/index-cmd.ts +88 -74
  112. package/src/mcp/tools/index.ts +96 -2
  113. package/src/mcp/tools/query.ts +95 -64
  114. package/src/mcp/tools/remove-collection.ts +2 -0
  115. package/src/mcp/tools/search.ts +36 -13
  116. package/src/mcp/tools/status.ts +11 -0
  117. package/src/mcp/tools/sync.ts +16 -14
  118. package/src/mcp/tools/trace.ts +143 -0
  119. package/src/mcp/tools/vsearch.ts +71 -38
  120. package/src/mcp/tools/workspace-write.ts +7 -3
  121. package/src/pipeline/answer.ts +167 -26
  122. package/src/pipeline/graph-retrieval.ts +15 -1
  123. package/src/pipeline/hybrid.ts +151 -43
  124. package/src/pipeline/search.ts +36 -3
  125. package/src/pipeline/trace-metadata.ts +47 -0
  126. package/src/pipeline/types.ts +43 -0
  127. package/src/pipeline/vsearch.ts +101 -38
  128. package/src/sdk/client.ts +380 -71
  129. package/src/sdk/documents.ts +48 -1
  130. package/src/sdk/index.ts +17 -0
  131. package/src/sdk/types.ts +28 -0
  132. package/src/serve/background-runtime.ts +12 -212
  133. package/src/serve/context-capsule.ts +67 -8
  134. package/src/serve/embed-scheduler.ts +74 -43
  135. package/src/serve/index.ts +9 -0
  136. package/src/serve/jobs.ts +78 -80
  137. package/src/serve/public/app.tsx +12 -1
  138. package/src/serve/public/components/HealthCenter.tsx +74 -1
  139. package/src/serve/public/globals.built.css +1 -1
  140. package/src/serve/public/lib/workspace-tabs.ts +2 -0
  141. package/src/serve/public/pages/Dashboard.tsx +11 -0
  142. package/src/serve/public/pages/TraceHistory.tsx +478 -0
  143. package/src/serve/public/pages/trace-history-detail.tsx +224 -0
  144. package/src/serve/resident-admission.ts +159 -0
  145. package/src/serve/resident-background-work.ts +39 -0
  146. package/src/serve/resident-request.ts +55 -0
  147. package/src/serve/resident-runtime.ts +490 -0
  148. package/src/serve/resident-status.ts +96 -0
  149. package/src/serve/retrieval-trace.ts +28 -0
  150. package/src/serve/routes/api.ts +629 -239
  151. package/src/serve/routes/mcp.ts +69 -0
  152. package/src/serve/routes/traces.ts +156 -0
  153. package/src/serve/server.ts +276 -37
  154. package/src/serve/status-model.ts +51 -0
  155. package/src/serve/status.ts +5 -0
  156. package/src/store/index.ts +31 -0
  157. package/src/store/migrations/014-retrieval-traces.ts +303 -0
  158. package/src/store/migrations/index.ts +2 -0
  159. package/src/store/retrieval-trace-codec.ts +384 -0
  160. package/src/store/sqlite/adapter.ts +179 -10
  161. package/src/store/sqlite/retrieval-trace-management-store.ts +341 -0
  162. package/src/store/sqlite/retrieval-trace-retention.ts +349 -0
  163. package/src/store/sqlite/retrieval-trace-rows.ts +267 -0
  164. package/src/store/sqlite/retrieval-trace-store.ts +515 -0
  165. package/src/store/types.ts +297 -0
  166. package/src/store/vector/sqlite-vec.ts +76 -1
  167. package/src/store/vector/types.ts +1 -1
@@ -0,0 +1,113 @@
1
+ /** Aggregate retrieval trace export with manifest-bound verification. */
2
+
3
+ import type {
4
+ RetrievalTraceBundle,
5
+ RetrievalTraceExportFormat,
6
+ StorePort,
7
+ StoreResult,
8
+ } from "../store/types";
9
+ import type {
10
+ ExportRetrievalTracesInput,
11
+ ExportRetrievalTracesResult,
12
+ RetrievalTraceArtifact,
13
+ } from "./retrieval-trace-management-types";
14
+
15
+ import { hashTraceCanonical } from "../store/retrieval-trace-codec";
16
+ import { err, ok } from "../store/types";
17
+ import { buildRetrievalQrelsArtifact } from "./retrieval-qrels";
18
+
19
+ const validateTraceIds = (traceIds: unknown): StoreResult<string[]> => {
20
+ if (
21
+ !Array.isArray(traceIds) ||
22
+ traceIds.some(
23
+ (traceId) => typeof traceId !== "string" || traceId.length < 1
24
+ )
25
+ ) {
26
+ return err("INVALID_INPUT", "Export trace IDs must be a string array");
27
+ }
28
+ const normalized = [...new Set(traceIds)].sort((left, right) =>
29
+ left.localeCompare(right)
30
+ );
31
+ return normalized.length < 1 || normalized.length > 10_000
32
+ ? err("INVALID_INPUT", "Export requires from 1 to 10000 trace IDs")
33
+ : ok(normalized);
34
+ };
35
+
36
+ const agenticArtifact = (
37
+ bundles: RetrievalTraceBundle[]
38
+ ): RetrievalTraceArtifact => ({
39
+ schemaVersion: "1.0",
40
+ format: "agentic-receipt",
41
+ traces: bundles.map(({ exports: _exports, ...trace }) => trace),
42
+ });
43
+
44
+ const buildArtifact = (
45
+ format: "agentic-receipt" | "qrels",
46
+ bundles: RetrievalTraceBundle[]
47
+ ): StoreResult<RetrievalTraceArtifact> => {
48
+ if (format === "agentic-receipt") return ok(agenticArtifact(bundles));
49
+ return buildRetrievalQrelsArtifact(bundles);
50
+ };
51
+
52
+ export const exportRetrievalTraces = async <
53
+ Format extends RetrievalTraceExportFormat,
54
+ >(
55
+ store: StorePort,
56
+ clock: () => number,
57
+ input: ExportRetrievalTracesInput<Format>
58
+ ): Promise<StoreResult<ExportRetrievalTracesResult<Format>>> => {
59
+ const format = input.format ?? "agentic-receipt";
60
+ if (!["agentic-receipt", "qrels"].includes(format)) {
61
+ return err("INVALID_INPUT", "Invalid retrieval trace export format");
62
+ }
63
+ const traceIds = validateTraceIds(input.traceIds);
64
+ if (!traceIds.ok) return traceIds;
65
+ const bundles: RetrievalTraceBundle[] = [];
66
+ for (const traceId of traceIds.value) {
67
+ const stored = await store.getRetrievalTrace(traceId);
68
+ if (!stored.ok) return stored;
69
+ if (!stored.value) return err("NOT_FOUND", "Retrieval trace not found");
70
+ if (stored.value.trace.status === "open") {
71
+ return err(
72
+ "CONSTRAINT_VIOLATION",
73
+ "Open retrieval traces cannot be exported"
74
+ );
75
+ }
76
+ bundles.push(stored.value);
77
+ }
78
+ const built = buildArtifact(format, bundles);
79
+ if (!built.ok) return built;
80
+ const artifactHash = hashTraceCanonical(built.value);
81
+ const exportId = `trace-export-${artifactHash.slice(0, 40)}`;
82
+ const appended = await store.appendRetrievalTraceExportManifest({
83
+ exportId,
84
+ traceIds: traceIds.value,
85
+ format,
86
+ artifactHash,
87
+ createdAtMs: clock(),
88
+ });
89
+ if (!appended.ok) return appended;
90
+ const complete = await store.getRetrievalTraceExportBundle(exportId);
91
+ if (!complete.ok) return complete;
92
+ if (!complete.value) {
93
+ return err("QUERY_FAILED", "Stored retrieval trace export is unavailable");
94
+ }
95
+ const reconstructed = buildArtifact(format, complete.value.traces);
96
+ if (!reconstructed.ok) return reconstructed;
97
+ if (
98
+ complete.value.manifest.traceIds.join("\0") !== traceIds.value.join("\0") ||
99
+ hashTraceCanonical(reconstructed.value) !==
100
+ complete.value.manifest.artifactHash
101
+ ) {
102
+ return err(
103
+ "CONSTRAINT_VIOLATION",
104
+ "manifest_hash_mismatch: stored retrieval trace export changed"
105
+ );
106
+ }
107
+ return ok({
108
+ schemaVersion: "1.0",
109
+ result: appended.value,
110
+ manifest: complete.value.manifest,
111
+ artifact: reconstructed.value,
112
+ } as ExportRetrievalTracesResult<Format>);
113
+ };
@@ -0,0 +1,27 @@
1
+ /** Deterministic set-like retrieval-filter normalization before persistence. */
2
+
3
+ const SET_ARRAY_KEYS = [
4
+ "categories",
5
+ "collections",
6
+ "exclude",
7
+ "tagsAll",
8
+ "tagsAny",
9
+ ] as const;
10
+
11
+ const compareCodeUnits = (left: string, right: string): number =>
12
+ left < right ? -1 : left > right ? 1 : 0;
13
+
14
+ export const canonicalizeRetrievalTraceFilters = <
15
+ Filters extends Record<string, unknown>,
16
+ >(
17
+ filters: Filters
18
+ ): Filters => {
19
+ const normalized: Record<string, unknown> = { ...filters };
20
+ for (const key of SET_ARRAY_KEYS) {
21
+ const values = filters[key];
22
+ if (Array.isArray(values)) {
23
+ normalized[key] = [...new Set(values)].sort(compareCodeUnits);
24
+ }
25
+ }
26
+ return normalized as Filters;
27
+ };
@@ -0,0 +1,19 @@
1
+ /** Canonical replay-filter parsing shared by qrels export and replay. */
2
+
3
+ import type { StoreResult } from "../store/types";
4
+
5
+ import { err, ok } from "../store/types";
6
+ import { traceFiltersSchema } from "./retrieval-trace";
7
+ import { canonicalizeRetrievalTraceFilters } from "./retrieval-trace-filter-normalization";
8
+
9
+ export type RetrievalTraceFilters = Record<string, unknown>;
10
+
11
+ export const parseRetrievalTraceFilters = (
12
+ value: unknown
13
+ ): StoreResult<RetrievalTraceFilters> => {
14
+ const parsed = traceFiltersSchema.safeParse(value);
15
+ if (!parsed.success) {
16
+ return err("INVALID_INPUT", `filters_incomplete: ${parsed.error.message}`);
17
+ }
18
+ return ok(canonicalizeRetrievalTraceFilters(parsed.data));
19
+ };
@@ -0,0 +1,247 @@
1
+ import type {
2
+ RetrievalTraceBundle,
3
+ RetrievalTraceCursor,
4
+ RetrievalTraceJudgmentRow,
5
+ StoreResult,
6
+ } from "../store/types";
7
+ import type {
8
+ LabelRetrievalTraceInput,
9
+ RetrievalTraceSummary,
10
+ } from "./retrieval-trace-management-types";
11
+
12
+ import { hashTraceCanonical } from "../store/retrieval-trace-codec";
13
+ import { err, ok } from "../store/types";
14
+
15
+ export type EvidenceTarget = {
16
+ docid?: string;
17
+ sourceHash?: string;
18
+ mirrorHash?: string;
19
+ uri?: string;
20
+ seq?: number;
21
+ startLine?: number;
22
+ endLine?: number;
23
+ passageHash?: string;
24
+ };
25
+
26
+ export interface EvidenceMatch {
27
+ target: EvidenceTarget;
28
+ runId: string | null;
29
+ }
30
+
31
+ export const compactTarget = (target: EvidenceTarget): EvidenceTarget =>
32
+ Object.fromEntries(
33
+ Object.entries(target).filter(([, value]) => value !== undefined)
34
+ ) as EvidenceTarget;
35
+
36
+ export const summaryOf = (
37
+ trace: RetrievalTraceBundle["trace"]
38
+ ): RetrievalTraceSummary => ({
39
+ traceId: trace.traceId,
40
+ schemaVersion: trace.schemaVersion,
41
+ redactionMode: trace.redactionMode,
42
+ replayCapable: trace.replayCapable,
43
+ status: trace.status,
44
+ queryShape: trace.queryShape,
45
+ goalShape: trace.goalShape,
46
+ fingerprints: trace.fingerprints,
47
+ createdAtMs: trace.createdAtMs,
48
+ updatedAtMs: trace.updatedAtMs,
49
+ expiresAtMs: trace.expiresAtMs,
50
+ byteSize: trace.byteSize,
51
+ creationDigest: trace.creationDigest,
52
+ });
53
+
54
+ const TRACE_CURSOR_PREFIX = "gno-trace-v1.";
55
+ const TRACE_CURSOR_KEYS = ["createdAtMs", "traceId"] as const;
56
+
57
+ export const encodeCursor = (cursor: RetrievalTraceCursor): string => {
58
+ const payload = new TextEncoder().encode(
59
+ JSON.stringify({
60
+ createdAtMs: cursor.createdAtMs,
61
+ traceId: cursor.traceId,
62
+ })
63
+ );
64
+ return `${TRACE_CURSOR_PREFIX}${payload.toBase64({
65
+ alphabet: "base64url",
66
+ omitPadding: true,
67
+ })}`;
68
+ };
69
+
70
+ export const decodeCursor = (
71
+ value: string | undefined
72
+ ): StoreResult<RetrievalTraceCursor | undefined> => {
73
+ if (value === undefined) return ok(undefined);
74
+ if (!value.startsWith(TRACE_CURSOR_PREFIX)) {
75
+ return err("INVALID_INPUT", "Invalid trace cursor");
76
+ }
77
+ let decoded: unknown;
78
+ try {
79
+ const bytes = Uint8Array.fromBase64(
80
+ value.slice(TRACE_CURSOR_PREFIX.length),
81
+ {
82
+ alphabet: "base64url",
83
+ }
84
+ );
85
+ decoded = JSON.parse(
86
+ new TextDecoder("utf-8", { fatal: true }).decode(bytes)
87
+ );
88
+ } catch {
89
+ return err("INVALID_INPUT", "Invalid trace cursor");
90
+ }
91
+ if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) {
92
+ return err("INVALID_INPUT", "Invalid trace cursor");
93
+ }
94
+ const record = decoded as Record<string, unknown>;
95
+ if (
96
+ Object.keys(record).length !== TRACE_CURSOR_KEYS.length ||
97
+ TRACE_CURSOR_KEYS.some((key) => !(key in record))
98
+ ) {
99
+ return err("INVALID_INPUT", "Invalid trace cursor");
100
+ }
101
+ const { createdAtMs, traceId } = record;
102
+ if (
103
+ !Number.isSafeInteger(createdAtMs) ||
104
+ (createdAtMs as number) < 0 ||
105
+ typeof traceId !== "string" ||
106
+ traceId.length < 1 ||
107
+ traceId.length > 128
108
+ ) {
109
+ return err("INVALID_INPUT", "Invalid trace cursor");
110
+ }
111
+ return ok({ createdAtMs: createdAtMs as number, traceId });
112
+ };
113
+
114
+ export const stableTarget = (value: unknown): EvidenceTarget | null => {
115
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
116
+ const record = value as Record<string, unknown>;
117
+ const target: EvidenceTarget = {};
118
+ for (const key of [
119
+ "docid",
120
+ "sourceHash",
121
+ "mirrorHash",
122
+ "uri",
123
+ "passageHash",
124
+ ] as const) {
125
+ if (typeof record[key] === "string") target[key] = record[key];
126
+ }
127
+ for (const key of ["seq", "startLine", "endLine"] as const) {
128
+ if (typeof record[key] === "number") target[key] = record[key];
129
+ }
130
+ return target.docid || target.sourceHash || target.mirrorHash || target.uri
131
+ ? target
132
+ : null;
133
+ };
134
+
135
+ const payloadEvidence = (
136
+ payload: Record<string, unknown>
137
+ ): EvidenceTarget[] => {
138
+ const found: EvidenceTarget[] = [];
139
+ for (const key of ["ranked", "evidence"] as const) {
140
+ const values = payload[key];
141
+ if (!Array.isArray(values)) continue;
142
+ for (const value of values) {
143
+ const target = stableTarget(value);
144
+ if (target) found.push(target);
145
+ }
146
+ }
147
+ return found;
148
+ };
149
+
150
+ export const allEvidence = (bundle: RetrievalTraceBundle): EvidenceMatch[] => [
151
+ ...bundle.runs.flatMap((run) =>
152
+ payloadEvidence(run.payload).map((target) => ({
153
+ target,
154
+ runId: run.runId,
155
+ }))
156
+ ),
157
+ ...bundle.events.flatMap((event) =>
158
+ payloadEvidence(event.payload).map((target) => ({
159
+ target,
160
+ runId: event.runId,
161
+ }))
162
+ ),
163
+ ];
164
+
165
+ export const refMatches = (target: EvidenceTarget, ref: string): boolean =>
166
+ [
167
+ target.uri,
168
+ target.docid,
169
+ target.sourceHash,
170
+ target.mirrorHash,
171
+ target.passageHash,
172
+ ].includes(ref);
173
+
174
+ export const applyTargetKind = (
175
+ target: EvidenceTarget,
176
+ input: LabelRetrievalTraceInput
177
+ ): StoreResult<EvidenceTarget> => {
178
+ const targetKind =
179
+ input.targetKind ??
180
+ (input.startLine === undefined
181
+ ? target.seq === undefined
182
+ ? "document"
183
+ : "chunk"
184
+ : "span");
185
+ if ((input.startLine === undefined) !== (input.endLine === undefined)) {
186
+ return err("INVALID_INPUT", "Trace span labels require both line bounds");
187
+ }
188
+ if (
189
+ input.startLine !== undefined &&
190
+ (input.startLine < 1 ||
191
+ input.endLine! < input.startLine ||
192
+ target.startLine !== input.startLine ||
193
+ target.endLine !== input.endLine)
194
+ ) {
195
+ return err(
196
+ "INVALID_INPUT",
197
+ "Trace label does not match an exact evidence span"
198
+ );
199
+ }
200
+ if (input.sourceHash && target.sourceHash !== input.sourceHash) {
201
+ return err(
202
+ "INVALID_INPUT",
203
+ "Trace label source hash does not match evidence"
204
+ );
205
+ }
206
+ if (input.docid && target.docid !== input.docid) {
207
+ return err("INVALID_INPUT", "Trace label docid does not match evidence");
208
+ }
209
+ if (targetKind === "span" && target.startLine === undefined) {
210
+ return err(
211
+ "INVALID_INPUT",
212
+ "Span labels require exact recorded evidence lines"
213
+ );
214
+ }
215
+ if (targetKind === "chunk" && target.seq === undefined) {
216
+ return err(
217
+ "INVALID_INPUT",
218
+ "Chunk labels require a recorded chunk sequence"
219
+ );
220
+ }
221
+ if (targetKind === "document") {
222
+ const { docid, sourceHash, mirrorHash, uri } = target;
223
+ return ok(compactTarget({ docid, sourceHash, mirrorHash, uri }));
224
+ }
225
+ return ok(target);
226
+ };
227
+
228
+ export const targetKey = (
229
+ targetKind: NonNullable<LabelRetrievalTraceInput["targetKind"]>,
230
+ target: EvidenceTarget
231
+ ): string => hashTraceCanonical({ targetKind, target });
232
+
233
+ export const latestForTarget = (
234
+ judgments: RetrievalTraceJudgmentRow[],
235
+ key: string
236
+ ): RetrievalTraceJudgmentRow | undefined =>
237
+ judgments
238
+ .filter(
239
+ (judgment) =>
240
+ targetKey(
241
+ judgment.targetKind as NonNullable<
242
+ LabelRetrievalTraceInput["targetKind"]
243
+ >,
244
+ stableTarget(judgment.target) ?? {}
245
+ ) === key
246
+ )
247
+ .at(-1);
@@ -0,0 +1,132 @@
1
+ import type {
2
+ RetrievalTraceAppendResult,
3
+ RetrievalTraceBundle,
4
+ RetrievalTraceDeleteCounts,
5
+ RetrievalTraceExportFormat,
6
+ RetrievalTraceExportManifestRow,
7
+ RetrievalTraceJudgmentLabel,
8
+ RetrievalTraceJudgmentRow,
9
+ RetrievalTraceJudgmentTargetKind,
10
+ RetrievalTracePurgeResult as StoredRetrievalTracePurgeResult,
11
+ RetrievalTraceRow,
12
+ } from "../store/types";
13
+ import type { RetrievalTraceQrelsArtifact } from "./retrieval-qrels";
14
+
15
+ export interface RetrievalTraceSummary {
16
+ traceId: string;
17
+ schemaVersion: "1.0";
18
+ redactionMode: RetrievalTraceRow["redactionMode"];
19
+ replayCapable: boolean;
20
+ status: RetrievalTraceRow["status"];
21
+ queryShape: RetrievalTraceRow["queryShape"];
22
+ goalShape: RetrievalTraceRow["goalShape"];
23
+ fingerprints: RetrievalTraceRow["fingerprints"];
24
+ createdAtMs: number;
25
+ updatedAtMs: number;
26
+ expiresAtMs: number;
27
+ byteSize: number;
28
+ creationDigest: string;
29
+ }
30
+
31
+ export interface RetrievalTraceListOptions {
32
+ limit?: number;
33
+ cursor?: string;
34
+ }
35
+
36
+ export interface RetrievalTraceListResult {
37
+ schemaVersion: "1.0";
38
+ traces: RetrievalTraceSummary[];
39
+ nextCursor: string | null;
40
+ }
41
+
42
+ export interface RetrievalTraceDetailOptions {
43
+ detailLimit?: number;
44
+ }
45
+
46
+ export interface RetrievalTraceDetail extends Omit<
47
+ RetrievalTraceBundle,
48
+ "runs" | "events" | "judgments" | "exports"
49
+ > {
50
+ schemaVersion: "1.0";
51
+ runs: RetrievalTraceBundle["runs"];
52
+ events: RetrievalTraceBundle["events"];
53
+ judgments: RetrievalTraceBundle["judgments"];
54
+ exports: RetrievalTraceBundle["exports"];
55
+ totals: {
56
+ runs: number;
57
+ events: number;
58
+ judgments: number;
59
+ exports: number;
60
+ };
61
+ truncated: {
62
+ runs: boolean;
63
+ events: boolean;
64
+ judgments: boolean;
65
+ exports: boolean;
66
+ };
67
+ }
68
+
69
+ export interface LabelRetrievalTraceInput {
70
+ traceId: string;
71
+ label: RetrievalTraceJudgmentLabel;
72
+ targetRef: string;
73
+ targetKind?: Exclude<RetrievalTraceJudgmentTargetKind, "query">;
74
+ startLine?: number;
75
+ endLine?: number;
76
+ sourceHash?: string;
77
+ docid?: string;
78
+ idempotencyKey?: string;
79
+ }
80
+
81
+ export interface LabelRetrievalTraceResult {
82
+ schemaVersion: "1.0";
83
+ result: RetrievalTraceAppendResult;
84
+ judgment: RetrievalTraceJudgmentRow;
85
+ }
86
+
87
+ export interface RetrievalTraceAgenticArtifact {
88
+ schemaVersion: "1.0";
89
+ format: "agentic-receipt";
90
+ traces: Array<Omit<RetrievalTraceBundle, "exports">>;
91
+ }
92
+
93
+ export type RetrievalTraceArtifact =
94
+ | RetrievalTraceAgenticArtifact
95
+ | RetrievalTraceQrelsArtifact;
96
+
97
+ export interface ExportRetrievalTracesInput<
98
+ Format extends RetrievalTraceExportFormat = "agentic-receipt",
99
+ > {
100
+ traceIds: string[];
101
+ format?: Format;
102
+ }
103
+
104
+ export interface ExportRetrievalTracesResult<
105
+ Format extends RetrievalTraceExportFormat = "agentic-receipt",
106
+ > {
107
+ schemaVersion: "1.0";
108
+ result: RetrievalTraceAppendResult;
109
+ manifest: RetrievalTraceExportManifestRow;
110
+ artifact: Format extends "qrels"
111
+ ? RetrievalTraceQrelsArtifact
112
+ : RetrievalTraceAgenticArtifact;
113
+ }
114
+
115
+ export interface DeleteRetrievalTraceResult {
116
+ schemaVersion: "1.0";
117
+ traceId: string;
118
+ deleted: boolean;
119
+ counts: RetrievalTraceDeleteCounts;
120
+ }
121
+
122
+ export interface PurgeRetrievalTracesResult extends StoredRetrievalTracePurgeResult {
123
+ schemaVersion: "1.0";
124
+ }
125
+
126
+ export type RetrievalTraceListRequest = RetrievalTraceListOptions;
127
+ export type RetrievalTraceLabelRequest = LabelRetrievalTraceInput;
128
+ export type RetrievalTraceExportRequest = ExportRetrievalTracesInput;
129
+ export type RetrievalTraceLabelResult = LabelRetrievalTraceResult;
130
+ export type RetrievalTraceExportResult = ExportRetrievalTracesResult;
131
+ export type RetrievalTraceDeleteResult = DeleteRetrievalTraceResult;
132
+ export type RetrievalTracePurgeResult = PurgeRetrievalTracesResult;