@gmickel/gno 1.19.0 → 1.21.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 (85) hide show
  1. package/README.md +28 -8
  2. package/assets/skill/SKILL.md +73 -27
  3. package/assets/skill/mcp-reference.md +7 -2
  4. package/assets/skill/recipes/citation-and-provenance.md +32 -9
  5. package/package.json +1 -1
  6. package/spec/cli.md +142 -17
  7. package/spec/db/schema.sql +170 -0
  8. package/spec/evals-agentic.md +87 -5
  9. package/spec/mcp.md +75 -3
  10. package/spec/output-schemas/ask.schema.json +198 -0
  11. package/spec/output-schemas/capsule-reverified-event.schema.json +47 -0
  12. package/spec/output-schemas/changes.schema.json +280 -0
  13. package/spec/output-schemas/claim-verification.schema.json +291 -0
  14. package/spec/output-schemas/context-capsule-v1.schema.json +36 -1
  15. package/spec/output-schemas/document-diff.schema.json +185 -0
  16. package/spec/output-schemas/impact.schema.json +122 -0
  17. package/spec/output-schemas/saved-capsule-list.schema.json +16 -0
  18. package/spec/output-schemas/saved-capsule-registration.schema.json +172 -0
  19. package/spec/output-schemas/saved-capsule-reverification.schema.json +59 -0
  20. package/spec/output-schemas/saved-capsule-unwatch.schema.json +16 -0
  21. package/spec/output-schemas/saved-capsule-watch.schema.json +17 -0
  22. package/src/app/context-runtime-contract.ts +10 -5
  23. package/src/app/context-runtime-input.ts +29 -1
  24. package/src/app/context-runtime-types.ts +4 -0
  25. package/src/app/context-runtime.ts +5 -1
  26. package/src/app/context-surface.ts +4 -0
  27. package/src/app/verified-ask.ts +291 -0
  28. package/src/cli/commands/ask-format.ts +255 -0
  29. package/src/cli/commands/ask.ts +40 -149
  30. package/src/cli/commands/changes.ts +160 -0
  31. package/src/cli/commands/context-saved.ts +189 -0
  32. package/src/cli/options.ts +8 -0
  33. package/src/cli/program.ts +227 -1
  34. package/src/core/capsule-registry.ts +279 -0
  35. package/src/core/capsule-reverification-scheduler.ts +218 -0
  36. package/src/core/capsule-reverification.ts +289 -0
  37. package/src/core/change-diff.ts +182 -0
  38. package/src/core/change-journal.ts +228 -0
  39. package/src/core/context-budget.ts +6 -0
  40. package/src/core/context-capsule-retrieval-schema.ts +4 -0
  41. package/src/core/context-capsule-schema.ts +17 -0
  42. package/src/core/context-capsule-validation.ts +3 -2
  43. package/src/core/context-capsule.ts +18 -0
  44. package/src/core/context-compiler.ts +33 -21
  45. package/src/core/context-evidence.ts +6 -0
  46. package/src/core/knowledge-delta.ts +395 -0
  47. package/src/core/knowledge-impact.ts +202 -0
  48. package/src/core/retrieval-trace-evidence-origin.ts +3 -0
  49. package/src/core/retrieval-trace-session.ts +15 -2
  50. package/src/ingestion/sync.ts +214 -165
  51. package/src/llm/errors.ts +10 -1
  52. package/src/llm/httpGeneration.ts +11 -1
  53. package/src/llm/nodeLlamaCpp/generation.ts +54 -10
  54. package/src/llm/types.ts +6 -0
  55. package/src/mcp/tools/ask.ts +228 -0
  56. package/src/mcp/tools/changes.ts +80 -0
  57. package/src/mcp/tools/context.ts +28 -7
  58. package/src/mcp/tools/index.ts +38 -0
  59. package/src/pipeline/claim-verification-schema.ts +235 -0
  60. package/src/pipeline/claim-verification.ts +487 -0
  61. package/src/pipeline/claim-verifier.ts +474 -0
  62. package/src/pipeline/types.ts +25 -0
  63. package/src/sdk/client.ts +77 -2
  64. package/src/sdk/index.ts +7 -0
  65. package/src/sdk/types.ts +22 -0
  66. package/src/serve/doc-events.ts +12 -1
  67. package/src/serve/public/components/AskVerificationPanel.tsx +189 -0
  68. package/src/serve/public/globals.built.css +1 -1
  69. package/src/serve/public/pages/Ask.tsx +42 -4
  70. package/src/serve/resident-runtime.ts +22 -0
  71. package/src/serve/routes/api.ts +162 -3
  72. package/src/serve/routes/changes.ts +102 -0
  73. package/src/serve/server.ts +34 -0
  74. package/src/serve/watch-service.ts +9 -0
  75. package/src/store/index.ts +21 -0
  76. package/src/store/migrations/015-document-change-journal.ts +85 -0
  77. package/src/store/migrations/016-saved-capsules.ts +131 -0
  78. package/src/store/migrations/017-document-change-retention-counters.ts +33 -0
  79. package/src/store/migrations/018-saved-capsule-registration-epoch.ts +24 -0
  80. package/src/store/migrations/019-saved-capsule-registration-generation.ts +53 -0
  81. package/src/store/migrations/index.ts +10 -0
  82. package/src/store/sqlite/adapter.ts +291 -7
  83. package/src/store/sqlite/capsule-registry-store.ts +534 -0
  84. package/src/store/sqlite/change-journal-store.ts +473 -0
  85. package/src/store/types.ts +262 -0
package/src/sdk/types.ts CHANGED
@@ -17,6 +17,13 @@ import type {
17
17
  } from "../core/context-capsule";
18
18
  import type { ContextEvidenceErrorCode } from "../core/context-evidence";
19
19
  import type { ContextVerifierErrorCode } from "../core/context-verifier";
20
+ import type {
21
+ KnowledgeChangesResult,
22
+ KnowledgeDiffResult,
23
+ KnowledgeImpactInput,
24
+ KnowledgeImpactResult,
25
+ ListKnowledgeChangesInput,
26
+ } from "../core/knowledge-delta";
20
27
  import type { NoteCollisionPolicy } from "../core/note-creation";
21
28
  import type { NotePresetId } from "../core/note-presets";
22
29
  import type {
@@ -52,6 +59,15 @@ export type {
52
59
  SyncResult,
53
60
  };
54
61
  export type { AskOptions, HybridSearchOptions } from "../pipeline/types";
62
+ export type {
63
+ KnowledgeChange,
64
+ KnowledgeChangesResult,
65
+ KnowledgeDiffResult,
66
+ KnowledgeImpactEvidenceStep,
67
+ KnowledgeImpactInput,
68
+ KnowledgeImpactResult,
69
+ ListKnowledgeChangesInput,
70
+ } from "../core/knowledge-delta";
55
71
  export type { Collection, Config as GnoConfig, Context } from "../config/types";
56
72
  export type { GetResponse as GnoGetResult } from "../cli/commands/get";
57
73
  export type {
@@ -233,6 +249,12 @@ export interface GnoClient {
233
249
  list(
234
250
  options?: GnoListOptions
235
251
  ): Promise<import("../cli/commands/ls").LsResponse>;
252
+ changes(options?: ListKnowledgeChangesInput): Promise<KnowledgeChangesResult>;
253
+ diff(ref: string, changeId?: string): Promise<KnowledgeDiffResult>;
254
+ impact(
255
+ ref: string,
256
+ options?: KnowledgeImpactInput
257
+ ): Promise<KnowledgeImpactResult>;
236
258
  status(): Promise<IndexStatus>;
237
259
  listRetrievalTraces(
238
260
  options?: RetrievalTraceListRequest
@@ -1,6 +1,6 @@
1
1
  export type DocumentEventOrigin = "watcher" | "save" | "create";
2
2
 
3
- export interface DocumentEvent {
3
+ export interface DocumentChangedEvent {
4
4
  type: "document-changed";
5
5
  uri: string;
6
6
  collection: string;
@@ -9,6 +9,17 @@ export interface DocumentEvent {
9
9
  changedAt: string;
10
10
  }
11
11
 
12
+ export interface CapsuleReverifiedEvent {
13
+ type: "capsule-reverified";
14
+ registrationId: string;
15
+ capsuleId: string;
16
+ operationStatus: "completed" | "failed";
17
+ affectedQuestionState: "unaffected" | "affected" | "unknown";
18
+ changedAt: string;
19
+ }
20
+
21
+ export type DocumentEvent = DocumentChangedEvent | CapsuleReverifiedEvent;
22
+
12
23
  export interface DocumentEventBusState {
13
24
  connectedClients: number;
14
25
  retryMs: number;
@@ -0,0 +1,189 @@
1
+ import { AlertTriangle, CheckCircle2, CircleHelp, ShieldX } from "lucide-react";
2
+
3
+ import type { AskResult } from "../../../pipeline/types";
4
+
5
+ import { cn } from "../lib/utils";
6
+ import { Badge } from "./ui/badge";
7
+
8
+ export type AskVerification = NonNullable<AskResult["verification"]>;
9
+
10
+ interface AskVerificationPanelProps {
11
+ navigate: (to: string) => void;
12
+ verification: AskVerification;
13
+ }
14
+
15
+ const STATUS_PRESENTATION = {
16
+ supported: {
17
+ label: "supported",
18
+ icon: CheckCircle2,
19
+ className: "border-emerald-500/30 bg-emerald-500/10 text-emerald-300",
20
+ },
21
+ contradicted: {
22
+ label: "contradicted",
23
+ icon: ShieldX,
24
+ className: "border-destructive/40 bg-destructive/10 text-destructive",
25
+ },
26
+ insufficient: {
27
+ label: "insufficient",
28
+ icon: AlertTriangle,
29
+ className: "border-amber-500/30 bg-amber-500/10 text-amber-300",
30
+ },
31
+ uncertain: {
32
+ label: "uncertain",
33
+ icon: CircleHelp,
34
+ className: "border-sky-500/30 bg-sky-500/10 text-sky-300",
35
+ },
36
+ } as const;
37
+
38
+ const evidenceLabel = (uri: string, startLine: number, endLine: number) =>
39
+ `${uri}:L${startLine}${startLine === endLine ? "" : `-L${endLine}`}`;
40
+
41
+ export function AskVerificationPanel({
42
+ navigate,
43
+ verification,
44
+ }: AskVerificationPanelProps) {
45
+ const { claims, capsule, semantic } = verification;
46
+ const degradedCapabilities = Object.entries(
47
+ capsule.retrieval.capabilityStates
48
+ ).filter(([, state]) => state.requested && state.outcome !== "used");
49
+ const gaps = capsule.coverage.gaps;
50
+
51
+ return (
52
+ <details className="group rounded-lg border border-border/50 bg-card/55">
53
+ <summary className="flex cursor-pointer list-none items-center justify-between gap-3 px-4 py-3">
54
+ <div className="min-w-0">
55
+ <div className="flex flex-wrap items-center gap-2">
56
+ <span className="font-medium text-sm">
57
+ {claims.answerStatus === "verified"
58
+ ? "All claims verified"
59
+ : "Answer withheld"}
60
+ </span>
61
+ <Badge
62
+ className="font-mono text-[9px]"
63
+ variant={
64
+ claims.answerStatus === "verified" ? "default" : "outline"
65
+ }
66
+ >
67
+ {claims.coverage.supportedClaims}/{claims.coverage.totalClaims}{" "}
68
+ supported
69
+ </Badge>
70
+ </div>
71
+ <p className="mt-1 text-muted-foreground text-xs">
72
+ {claims.abstentionReason ??
73
+ `${claims.coverage.supportedRatio * 100}% support coverage`}
74
+ </p>
75
+ </div>
76
+ <span className="shrink-0 font-mono text-[10px] text-muted-foreground group-open:hidden">
77
+ details
78
+ </span>
79
+ </summary>
80
+
81
+ <div className="space-y-4 border-border/40 border-t px-4 py-4">
82
+ <div className="flex flex-wrap gap-2">
83
+ <Badge className="font-mono text-[9px]" variant="outline">
84
+ semantic: {semantic.status}/{semantic.reason}
85
+ </Badge>
86
+ {degradedCapabilities.map(([name, state]) => (
87
+ <Badge
88
+ className="font-mono text-[9px]"
89
+ key={name}
90
+ variant="outline"
91
+ >
92
+ {name}: {state.outcome}
93
+ {state.fallbackReasons.length > 0
94
+ ? ` (${state.fallbackReasons.join(", ")})`
95
+ : ""}
96
+ </Badge>
97
+ ))}
98
+ </div>
99
+
100
+ <div className="grid grid-cols-2 gap-2 font-mono text-[10px] text-muted-foreground sm:grid-cols-4">
101
+ <span>{claims.coverage.supportedClaims} supported</span>
102
+ <span>{claims.coverage.contradictedClaims} contradicted</span>
103
+ <span>{claims.coverage.insufficientClaims} insufficient</span>
104
+ <span>{claims.coverage.uncertainClaims} uncertain</span>
105
+ </div>
106
+
107
+ <div className="space-y-2">
108
+ {claims.claims.map((claim) => {
109
+ const presentation = STATUS_PRESENTATION[claim.status];
110
+ const StatusIcon = presentation.icon;
111
+ return (
112
+ <details
113
+ className="rounded-md border border-border/35 bg-background/20"
114
+ key={claim.claimId}
115
+ >
116
+ <summary className="flex cursor-pointer list-none items-start gap-2 px-3 py-2">
117
+ <StatusIcon className="mt-0.5 size-3.5 shrink-0" />
118
+ <span className="min-w-0 flex-1 text-xs">{claim.text}</span>
119
+ <Badge
120
+ className={cn(
121
+ "shrink-0 font-mono text-[9px]",
122
+ presentation.className
123
+ )}
124
+ variant="outline"
125
+ >
126
+ {presentation.label}
127
+ </Badge>
128
+ </summary>
129
+ <div className="space-y-2 border-border/30 border-t px-3 py-2">
130
+ {claim.evidence.length > 0 ? (
131
+ claim.evidence.map((evidence) => (
132
+ <button
133
+ className="block w-full truncate text-left font-mono text-[10px] text-primary hover:underline"
134
+ key={evidence.evidenceId}
135
+ onClick={() =>
136
+ navigate(
137
+ `/doc?uri=${encodeURIComponent(evidence.uri)}`
138
+ )
139
+ }
140
+ title={evidenceLabel(
141
+ evidence.uri,
142
+ evidence.startLine,
143
+ evidence.endLine
144
+ )}
145
+ type="button"
146
+ >
147
+ {evidenceLabel(
148
+ evidence.uri,
149
+ evidence.startLine,
150
+ evidence.endLine
151
+ )}
152
+ </button>
153
+ ))
154
+ ) : (
155
+ <p className="text-muted-foreground text-xs">
156
+ No retained evidence span.
157
+ </p>
158
+ )}
159
+ <p className="font-mono text-[10px] text-muted-foreground">
160
+ {claim.rationaleCode}
161
+ {claim.confidence === null
162
+ ? ""
163
+ : ` · confidence ${claim.confidence.toFixed(2)}`}
164
+ </p>
165
+ </div>
166
+ </details>
167
+ );
168
+ })}
169
+ </div>
170
+
171
+ {(capsule.coverage.unresolvedFacets.length > 0 || gaps.length > 0) && (
172
+ <div className="rounded-md border border-amber-500/25 bg-amber-500/5 px-3 py-2">
173
+ <p className="font-medium text-amber-200 text-xs">Evidence gaps</p>
174
+ <ul className="mt-1 space-y-1 font-mono text-[10px] text-muted-foreground">
175
+ {capsule.coverage.unresolvedFacets.map((facet) => (
176
+ <li key={`facet:${facet}`}>unresolved facet: {facet}</li>
177
+ ))}
178
+ {gaps.map((gap) => (
179
+ <li key={`${gap.facet}:${gap.code}`}>
180
+ {gap.facet}: {gap.code}
181
+ </li>
182
+ ))}
183
+ </ul>
184
+ </div>
185
+ )}
186
+ </div>
187
+ </details>
188
+ );
189
+ }