@gmickel/gno 1.19.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.
Files changed (45) hide show
  1. package/README.md +12 -7
  2. package/assets/skill/SKILL.md +27 -12
  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 +42 -17
  7. package/spec/evals-agentic.md +87 -5
  8. package/spec/mcp.md +53 -3
  9. package/spec/output-schemas/ask.schema.json +198 -0
  10. package/spec/output-schemas/claim-verification.schema.json +291 -0
  11. package/spec/output-schemas/context-capsule-v1.schema.json +36 -1
  12. package/src/app/context-runtime-contract.ts +10 -5
  13. package/src/app/context-runtime-input.ts +29 -1
  14. package/src/app/context-runtime-types.ts +4 -0
  15. package/src/app/context-runtime.ts +5 -1
  16. package/src/app/context-surface.ts +4 -0
  17. package/src/app/verified-ask.ts +291 -0
  18. package/src/cli/commands/ask-format.ts +255 -0
  19. package/src/cli/commands/ask.ts +40 -149
  20. package/src/cli/program.ts +32 -1
  21. package/src/core/context-budget.ts +6 -0
  22. package/src/core/context-capsule-retrieval-schema.ts +4 -0
  23. package/src/core/context-capsule-schema.ts +17 -0
  24. package/src/core/context-capsule-validation.ts +3 -2
  25. package/src/core/context-capsule.ts +18 -0
  26. package/src/core/context-compiler.ts +33 -21
  27. package/src/core/context-evidence.ts +6 -0
  28. package/src/core/retrieval-trace-evidence-origin.ts +3 -0
  29. package/src/core/retrieval-trace-session.ts +15 -2
  30. package/src/llm/errors.ts +10 -1
  31. package/src/llm/httpGeneration.ts +11 -1
  32. package/src/llm/nodeLlamaCpp/generation.ts +54 -10
  33. package/src/llm/types.ts +6 -0
  34. package/src/mcp/tools/ask.ts +228 -0
  35. package/src/mcp/tools/context.ts +28 -7
  36. package/src/mcp/tools/index.ts +9 -0
  37. package/src/pipeline/claim-verification-schema.ts +235 -0
  38. package/src/pipeline/claim-verification.ts +487 -0
  39. package/src/pipeline/claim-verifier.ts +474 -0
  40. package/src/pipeline/types.ts +25 -0
  41. package/src/sdk/client.ts +35 -2
  42. package/src/serve/public/components/AskVerificationPanel.tsx +189 -0
  43. package/src/serve/public/globals.built.css +1 -1
  44. package/src/serve/public/pages/Ask.tsx +42 -4
  45. package/src/serve/routes/api.ts +149 -3
@@ -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
+ }