@thehammer/template-verification 0.2.1 → 0.2.2
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 +24 -7
- package/dist/lib/sources.d.ts +4 -2
- package/dist/template-verification.js +327 -325
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -2,12 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
A read-write **verification overlay** for rendered template apps. It overlays a
|
|
4
4
|
trust layer on top of an already-rendered document template: per-data-point
|
|
5
|
-
confidence
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
`
|
|
5
|
+
confidence pills + verified check chips, discrepancy indicators, and a
|
|
6
|
+
click-through **Inspector** dialog — a hero strip (resolved value, gradient
|
|
7
|
+
confidence meter, discrepancy alert) over three tabs:
|
|
8
|
+
|
|
9
|
+
- **Evidence** — readonly-markdown reasoning, cited-text quote, an embedded
|
|
10
|
+
`DanxFileViewer` over the cited source pages, and per-document drill-down
|
|
11
|
+
to the FULL parent PDF in a stacked dialog.
|
|
12
|
+
- **Candidates** — the resolution flow: one card per candidate
|
|
13
|
+
(override/extracted/claim) with Accept actions + custom-value entry;
|
|
14
|
+
saves toast and flip the in-document pill to a verified chip.
|
|
15
|
+
- **Audit trail** — the LLM calls behind the data point (model, status,
|
|
16
|
+
timing, collapsible JSON request/response), lazy-fetched from the host's
|
|
17
|
+
token-sealed `audit_url`. Tab hidden when the host mints none.
|
|
18
|
+
|
|
19
|
+
`VerificationChrome` adds a review-progress meter (X of Y human-verified),
|
|
20
|
+
a needs-review jump button, and completion celebration.
|
|
21
|
+
|
|
22
|
+
Render data + `__meta` arrive via a single `initVerification()` call — the
|
|
23
|
+
only network the library touches is the host-supplied `saveOverride`
|
|
24
|
+
transport and the optional `auditUrl` endpoint. Backend-agnostic and
|
|
25
|
+
unit-testable standalone.
|
|
11
26
|
|
|
12
27
|
## Install
|
|
13
28
|
|
|
@@ -51,7 +66,9 @@ async function saveOverride(args) {
|
|
|
51
66
|
initVerification({
|
|
52
67
|
data: props.data,
|
|
53
68
|
saveOverride,
|
|
54
|
-
workflowInputId: props.data.workflow_input_id
|
|
69
|
+
workflowInputId: props.data.__verification?.workflow_input_id,
|
|
70
|
+
// Token-sealed audit endpoint (optional) — enables the Inspector's Audit tab.
|
|
71
|
+
auditUrl: props.data.__verification?.audit_url ?? null
|
|
55
72
|
})
|
|
56
73
|
</script>
|
|
57
74
|
|
package/dist/lib/sources.d.ts
CHANGED
|
@@ -18,8 +18,10 @@ export interface SourceGroup {
|
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Group an extracted candidate's sources by file identity so the modal can render
|
|
21
|
-
* one block per file with its pages beneath. Links a group
|
|
22
|
-
* is present on any of its sources
|
|
21
|
+
* one block per file with its pages beneath. Links a group when a `file_url` (the
|
|
22
|
+
* idealized shape) is present on any of its sources, falling back to the resolved
|
|
23
|
+
* `file.url` (the live gpt-manager backend shape — `TemplateDataResource` never
|
|
24
|
+
* emits `file_url`, only `file: {id,name,url,mime,size,thumb}`).
|
|
23
25
|
*/
|
|
24
26
|
export declare function groupSources(sources?: VerificationSource[] | null): SourceGroup[];
|
|
25
27
|
/** Human page/citation label for a single source row. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ref as U, watch as ce, defineComponent as K, computed as
|
|
1
|
+
import { ref as U, watch as ce, defineComponent as K, computed as d, openBlock as l, createElementBlock as o, normalizeClass as A, createElementVNode as r, toDisplayString as y, createCommentVNode as _, createBlock as N, unref as i, withCtx as I, createTextVNode as T, createVNode as V, Fragment as L, renderList as M, withKeys as Te, withModifiers as Ue, renderSlot as Ne, withDirectives as Ae, isRef as ge, vModelCheckbox as Re } from "vue";
|
|
2
2
|
import { DanxChip as J, CodeViewer as xe, useToast as _e, DanxDialog as re, DanxProgressBar as we, DanxAlert as ye, DanxTabs as Le, MarkdownEditor as je, DanxFileViewer as be, DanxButton as se, DanxInput as Ee, DanxSkeleton as ze, DanxTooltip as Pe, DanxIcon as Me, gearIcon as Be, DanxBadge as Fe, DanxToastContainer as qe } from "@thehammer/danx-ui";
|
|
3
3
|
const P = "tv-chrome", ke = "template-verification:enabled";
|
|
4
4
|
let te = null;
|
|
@@ -84,15 +84,15 @@ function Qe(e) {
|
|
|
84
84
|
return { value: null, source: "none" };
|
|
85
85
|
}
|
|
86
86
|
function ie(e) {
|
|
87
|
-
var g,
|
|
88
|
-
const t = (
|
|
87
|
+
var g, m;
|
|
88
|
+
const t = (m = (g = e == null ? void 0 : e.candidates) == null ? void 0 : g.extracted) == null ? void 0 : m.reasoning;
|
|
89
89
|
if (t == null) return null;
|
|
90
90
|
const a = String(t).trim();
|
|
91
91
|
return a === "" ? null : a;
|
|
92
92
|
}
|
|
93
93
|
function oe(e) {
|
|
94
|
-
var g,
|
|
95
|
-
const t = (
|
|
94
|
+
var g, m;
|
|
95
|
+
const t = (m = (g = e == null ? void 0 : e.candidates) == null ? void 0 : g.extracted) == null ? void 0 : m.cited_text;
|
|
96
96
|
if (t == null) return null;
|
|
97
97
|
const a = String(t).trim();
|
|
98
98
|
return a === "" ? null : a;
|
|
@@ -109,18 +109,18 @@ function Xe(e) {
|
|
|
109
109
|
return JSON.stringify(e ?? null);
|
|
110
110
|
}
|
|
111
111
|
function Ze(e, t, a) {
|
|
112
|
-
var
|
|
113
|
-
const g = (
|
|
112
|
+
var s;
|
|
113
|
+
const g = (s = t.value) == null ? void 0 : s.anchor;
|
|
114
114
|
if (!e.saveOverride || !g) return null;
|
|
115
|
-
const
|
|
116
|
-
return async (
|
|
117
|
-
const b = await
|
|
115
|
+
const m = e.saveOverride;
|
|
116
|
+
return async (f, n) => {
|
|
117
|
+
const b = await m({
|
|
118
118
|
workflow_input_id: e.workflowInputId,
|
|
119
119
|
object_ids: g.object_ids,
|
|
120
120
|
field: g.field,
|
|
121
121
|
field_path: g.field_path,
|
|
122
|
-
value:
|
|
123
|
-
source_choice:
|
|
122
|
+
value: f,
|
|
123
|
+
source_choice: n
|
|
124
124
|
});
|
|
125
125
|
return a(b), b;
|
|
126
126
|
};
|
|
@@ -139,7 +139,7 @@ const et = ["data-status", "title"], tt = {
|
|
|
139
139
|
showLabel: { type: Boolean }
|
|
140
140
|
},
|
|
141
141
|
setup(e) {
|
|
142
|
-
const t = e, a =
|
|
142
|
+
const t = e, a = d(
|
|
143
143
|
() => t.status ?? ve(t.confidence)
|
|
144
144
|
), g = {
|
|
145
145
|
high: "✔",
|
|
@@ -149,14 +149,14 @@ const et = ["data-status", "title"], tt = {
|
|
|
149
149
|
low: "✕",
|
|
150
150
|
// x
|
|
151
151
|
unverifiable: "?"
|
|
152
|
-
},
|
|
153
|
-
return (
|
|
154
|
-
class: A(["tv-confidence-icon inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-semibold leading-none",
|
|
152
|
+
}, m = d(() => g[a.value]), s = d(() => Ge[a.value]), f = d(() => ae[a.value]);
|
|
153
|
+
return (n, b) => (l(), o("span", {
|
|
154
|
+
class: A(["tv-confidence-icon inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-semibold leading-none", s.value]),
|
|
155
155
|
"data-status": a.value,
|
|
156
|
-
title:
|
|
156
|
+
title: f.value
|
|
157
157
|
}, [
|
|
158
|
-
|
|
159
|
-
e.showLabel ? (l(),
|
|
158
|
+
r("span", tt, y(m.value), 1),
|
|
159
|
+
e.showLabel ? (l(), o("span", at, y(f.value), 1)) : _("", !0)
|
|
160
160
|
], 10, et));
|
|
161
161
|
}
|
|
162
162
|
});
|
|
@@ -164,25 +164,26 @@ async function lt(e, t) {
|
|
|
164
164
|
const a = t.object_ids.at(-1), g = new URLSearchParams({
|
|
165
165
|
object_id: String(a),
|
|
166
166
|
field: t.field
|
|
167
|
-
}),
|
|
168
|
-
if (!
|
|
167
|
+
}), m = e.includes("?") ? "&" : "?", s = await fetch(`${e}${m}${g}`);
|
|
168
|
+
if (!s.ok)
|
|
169
169
|
throw new Error(
|
|
170
|
-
`data-point-audit ${
|
|
170
|
+
`data-point-audit ${s.status}: ${await s.text()}`
|
|
171
171
|
);
|
|
172
|
-
return (await
|
|
172
|
+
return (await s.json()).data ?? [];
|
|
173
173
|
}
|
|
174
174
|
function De(e) {
|
|
175
|
+
var a, g, m;
|
|
175
176
|
if (!e || e.length === 0) return [];
|
|
176
177
|
const t = /* @__PURE__ */ new Map();
|
|
177
|
-
for (const
|
|
178
|
-
const
|
|
179
|
-
let
|
|
180
|
-
|
|
181
|
-
fileLabel: st(
|
|
182
|
-
fileUrl: a.
|
|
183
|
-
file:
|
|
178
|
+
for (const s of e) {
|
|
179
|
+
const f = nt(s);
|
|
180
|
+
let n = t.get(f);
|
|
181
|
+
n || (n = {
|
|
182
|
+
fileLabel: st(s),
|
|
183
|
+
fileUrl: s.file_url ?? ((a = s.file) == null ? void 0 : a.url),
|
|
184
|
+
file: s.file,
|
|
184
185
|
sources: []
|
|
185
|
-
}, t.set(
|
|
186
|
+
}, t.set(f, n)), !n.fileUrl && (s.file_url ?? ((g = s.file) == null ? void 0 : g.url)) && (n.fileUrl = s.file_url ?? ((m = s.file) == null ? void 0 : m.url)), !n.file && s.file && (n.file = s.file), n.sources.push(s);
|
|
186
187
|
}
|
|
187
188
|
return [...t.values()];
|
|
188
189
|
}
|
|
@@ -195,7 +196,8 @@ function st(e) {
|
|
|
195
196
|
return (t = e.file) != null && t.name ? e.file.name : e.file_name ? e.file_name : e.file_id !== void 0 && e.file_id !== null ? `File ${e.file_id}` : e.stored_file_id !== void 0 && e.stored_file_id !== null ? `File ${e.stored_file_id}` : e.source_type ? e.source_type : "Source";
|
|
196
197
|
}
|
|
197
198
|
function rt(e) {
|
|
198
|
-
|
|
199
|
+
const t = e.page ?? e.page_number;
|
|
200
|
+
return t != null ? `Page ${t}` : e.explanation ? String(e.explanation) : e.source_type ? String(e.source_type) : "Citation";
|
|
199
201
|
}
|
|
200
202
|
const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm" }, ot = { class: "tv-audit-call-header flex flex-wrap items-center gap-2 border-b border-gray-100 bg-gray-50 px-3 py-2" }, ut = {
|
|
201
203
|
key: 2,
|
|
@@ -212,24 +214,24 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
212
214
|
call: {}
|
|
213
215
|
},
|
|
214
216
|
setup(e) {
|
|
215
|
-
const t = e, a =
|
|
216
|
-
const
|
|
217
|
-
return
|
|
218
|
-
}), g =
|
|
219
|
-
const
|
|
220
|
-
return
|
|
221
|
-
}),
|
|
217
|
+
const t = e, a = d(() => {
|
|
218
|
+
const n = t.call.status_code;
|
|
219
|
+
return n == null ? "muted" : n >= 200 && n < 300 ? "success" : n >= 400 ? "danger" : "warning";
|
|
220
|
+
}), g = d(() => {
|
|
221
|
+
const n = t.call.run_time_ms;
|
|
222
|
+
return n == null ? null : n >= 1e3 ? `${(n / 1e3).toFixed(1)}s` : `${n}ms`;
|
|
223
|
+
}), m = d(() => {
|
|
222
224
|
if (!t.call.started_at) return null;
|
|
223
|
-
const
|
|
224
|
-
return Number.isNaN(
|
|
225
|
-
}),
|
|
225
|
+
const n = new Date(t.call.started_at);
|
|
226
|
+
return Number.isNaN(n.getTime()) ? t.call.started_at : n.toLocaleString();
|
|
227
|
+
}), s = d(
|
|
226
228
|
() => JSON.stringify(t.call.request ?? null, null, 2)
|
|
227
|
-
),
|
|
229
|
+
), f = d(
|
|
228
230
|
() => JSON.stringify(t.call.response ?? null, null, 2)
|
|
229
231
|
);
|
|
230
|
-
return (
|
|
231
|
-
|
|
232
|
-
e.call.model ? (l(), N(
|
|
232
|
+
return (n, b) => (l(), o("div", it, [
|
|
233
|
+
r("div", ot, [
|
|
234
|
+
e.call.model ? (l(), N(i(J), {
|
|
233
235
|
key: 0,
|
|
234
236
|
variant: "info",
|
|
235
237
|
size: "xs",
|
|
@@ -240,7 +242,7 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
240
242
|
]),
|
|
241
243
|
_: 1
|
|
242
244
|
})) : _("", !0),
|
|
243
|
-
e.call.service ? (l(), N(
|
|
245
|
+
e.call.service ? (l(), N(i(J), {
|
|
244
246
|
key: 1,
|
|
245
247
|
variant: "muted",
|
|
246
248
|
size: "xxs"
|
|
@@ -250,9 +252,9 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
250
252
|
]),
|
|
251
253
|
_: 1
|
|
252
254
|
})) : _("", !0),
|
|
253
|
-
e.call.endpoint ? (l(),
|
|
254
|
-
b[0] || (b[0] =
|
|
255
|
-
V(
|
|
255
|
+
e.call.endpoint ? (l(), o("span", ut, y(e.call.endpoint), 1)) : _("", !0),
|
|
256
|
+
b[0] || (b[0] = r("span", { class: "flex-1" }, null, -1)),
|
|
257
|
+
V(i(J), {
|
|
256
258
|
variant: a.value,
|
|
257
259
|
size: "xxs",
|
|
258
260
|
class: "tv-audit-status"
|
|
@@ -262,24 +264,24 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
262
264
|
]),
|
|
263
265
|
_: 1
|
|
264
266
|
}, 8, ["variant"]),
|
|
265
|
-
g.value ? (l(),
|
|
266
|
-
|
|
267
|
+
g.value ? (l(), o("span", dt, y(g.value), 1)) : _("", !0),
|
|
268
|
+
m.value ? (l(), o("span", ct, y(m.value), 1)) : _("", !0)
|
|
267
269
|
]),
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
b[1] || (b[1] =
|
|
271
|
-
V(
|
|
272
|
-
"model-value":
|
|
270
|
+
r("div", vt, [
|
|
271
|
+
r("div", null, [
|
|
272
|
+
b[1] || (b[1] = r("div", { class: "mb-1 text-[11px] font-semibold uppercase tracking-wider text-gray-400" }, " Request ", -1)),
|
|
273
|
+
V(i(xe), {
|
|
274
|
+
"model-value": s.value,
|
|
273
275
|
format: "json",
|
|
274
276
|
collapsible: "",
|
|
275
277
|
"default-collapsed": "",
|
|
276
278
|
class: "tv-audit-request"
|
|
277
279
|
}, null, 8, ["model-value"])
|
|
278
280
|
]),
|
|
279
|
-
|
|
280
|
-
b[2] || (b[2] =
|
|
281
|
-
V(
|
|
282
|
-
"model-value":
|
|
281
|
+
r("div", null, [
|
|
282
|
+
b[2] || (b[2] = r("div", { class: "mb-1 text-[11px] font-semibold uppercase tracking-wider text-gray-400" }, " Response ", -1)),
|
|
283
|
+
V(i(xe), {
|
|
284
|
+
"model-value": f.value,
|
|
283
285
|
format: "json",
|
|
284
286
|
collapsible: "",
|
|
285
287
|
"default-collapsed": "",
|
|
@@ -338,29 +340,29 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
338
340
|
},
|
|
339
341
|
emits: ["update:modelValue", "saved"],
|
|
340
342
|
setup(e, { emit: t }) {
|
|
341
|
-
const a = e, g = t,
|
|
343
|
+
const a = e, g = t, m = le(), s = _e(), f = d({
|
|
342
344
|
get: () => a.modelValue,
|
|
343
|
-
set: (
|
|
344
|
-
}),
|
|
345
|
-
var
|
|
346
|
-
return ((
|
|
347
|
-
}), k =
|
|
348
|
-
var
|
|
349
|
-
return De((
|
|
350
|
-
}), j =
|
|
351
|
-
(
|
|
345
|
+
set: (v) => g("update:modelValue", v)
|
|
346
|
+
}), n = d(() => fe(a.meta)), b = d(() => a.meta.candidates.extracted), $ = d(() => a.meta.candidates.claim), h = d(() => a.meta.candidates.override), x = d(() => {
|
|
347
|
+
var v;
|
|
348
|
+
return ((v = b.value) == null ? void 0 : v.confidence) ?? null;
|
|
349
|
+
}), k = d(() => ve(x.value)), S = d(() => ie(a.meta)), R = d(() => oe(a.meta)), O = d(() => {
|
|
350
|
+
var v;
|
|
351
|
+
return De((v = b.value) == null ? void 0 : v.sources);
|
|
352
|
+
}), j = d(() => (a.meta.anchor.field_path || a.label || "Data point").split(".").map(
|
|
353
|
+
(u) => u.replace(/\[\d+\]/g, "").replace(/_/g, " ").replace(/^\w/, (C) => C.toUpperCase())
|
|
352
354
|
).join(" › ")), H = {
|
|
353
355
|
high: "success",
|
|
354
356
|
medium: "warning",
|
|
355
357
|
low: "danger",
|
|
356
358
|
unverifiable: "muted"
|
|
357
|
-
}, E = U("evidence"), W =
|
|
358
|
-
var
|
|
359
|
-
const
|
|
359
|
+
}, E = U("evidence"), W = d(() => !!m.auditUrl), X = d(() => {
|
|
360
|
+
var u;
|
|
361
|
+
const v = [
|
|
360
362
|
{
|
|
361
363
|
value: "evidence",
|
|
362
364
|
label: "Evidence",
|
|
363
|
-
count: O.value.reduce((C,
|
|
365
|
+
count: O.value.reduce((C, c) => C + c.sources.length, 0)
|
|
364
366
|
},
|
|
365
367
|
{
|
|
366
368
|
value: "candidates",
|
|
@@ -368,38 +370,38 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
368
370
|
count: Q.value.length
|
|
369
371
|
}
|
|
370
372
|
];
|
|
371
|
-
return W.value &&
|
|
373
|
+
return W.value && v.push({
|
|
372
374
|
value: "audit",
|
|
373
375
|
label: "Audit trail",
|
|
374
|
-
count: ((
|
|
375
|
-
}),
|
|
376
|
-
}), q =
|
|
377
|
-
() => O.value.map((
|
|
378
|
-
), p = U(null), w =
|
|
379
|
-
const
|
|
380
|
-
if (!
|
|
381
|
-
const
|
|
382
|
-
(
|
|
376
|
+
count: ((u = F.value) == null ? void 0 : u.length) ?? void 0
|
|
377
|
+
}), v;
|
|
378
|
+
}), q = d(
|
|
379
|
+
() => O.value.map((v) => v.file).filter((v) => !!v)
|
|
380
|
+
), p = U(null), w = d(() => {
|
|
381
|
+
const v = p.value ?? q.value[0];
|
|
382
|
+
if (!v) return null;
|
|
383
|
+
const u = O.value.find(
|
|
384
|
+
(c) => c.file && String(c.file.id) === String(v.id)
|
|
383
385
|
);
|
|
384
|
-
if (!
|
|
385
|
-
const C =
|
|
386
|
+
if (!u) return null;
|
|
387
|
+
const C = u.sources.find((c) => c.explanation);
|
|
386
388
|
return (C == null ? void 0 : C.explanation) ?? null;
|
|
387
|
-
}), D =
|
|
388
|
-
const
|
|
389
|
-
for (const
|
|
390
|
-
for (const C of
|
|
391
|
-
const
|
|
392
|
-
|
|
389
|
+
}), D = d(() => {
|
|
390
|
+
const v = /* @__PURE__ */ new Map();
|
|
391
|
+
for (const u of O.value)
|
|
392
|
+
for (const C of u.sources) {
|
|
393
|
+
const c = C.original_file;
|
|
394
|
+
c && !v.has(String(c.id)) && v.set(String(c.id), c);
|
|
393
395
|
}
|
|
394
|
-
return [...
|
|
395
|
-
}), z = U(null), G =
|
|
396
|
+
return [...v.values()];
|
|
397
|
+
}), z = U(null), G = d({
|
|
396
398
|
get: () => z.value !== null,
|
|
397
|
-
set: (
|
|
398
|
-
|
|
399
|
+
set: (v) => {
|
|
400
|
+
v || (z.value = null);
|
|
399
401
|
}
|
|
400
|
-
}), Q =
|
|
401
|
-
const
|
|
402
|
-
return h.value &&
|
|
402
|
+
}), Q = d(() => {
|
|
403
|
+
const v = [];
|
|
404
|
+
return h.value && v.push({
|
|
403
405
|
key: "override",
|
|
404
406
|
title: "Human override",
|
|
405
407
|
variant: "success",
|
|
@@ -408,60 +410,60 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
408
410
|
h.value.source_choice ? `basis: ${h.value.source_choice}` : null,
|
|
409
411
|
h.value.set_at ? new Date(h.value.set_at).toLocaleString() : null
|
|
410
412
|
].filter(Boolean).join(" · "),
|
|
411
|
-
winner:
|
|
412
|
-
}), b.value &&
|
|
413
|
+
winner: n.value.source === "override"
|
|
414
|
+
}), b.value && v.push({
|
|
413
415
|
key: "extracted",
|
|
414
416
|
title: "Extracted",
|
|
415
417
|
variant: H[k.value],
|
|
416
418
|
value: b.value.value,
|
|
417
419
|
detail: x.value != null ? `Confidence ${x.value}/5 · ${ae[k.value]}` : "No confidence recorded",
|
|
418
420
|
accept: a.save ? () => {
|
|
419
|
-
var
|
|
420
|
-
return ne(pe((
|
|
421
|
+
var u;
|
|
422
|
+
return ne(pe((u = b.value) == null ? void 0 : u.value), "extracted");
|
|
421
423
|
} : void 0,
|
|
422
|
-
winner:
|
|
423
|
-
}), $.value &&
|
|
424
|
+
winner: n.value.source === "extracted"
|
|
425
|
+
}), $.value && v.push({
|
|
424
426
|
key: "claim",
|
|
425
427
|
title: "Claim",
|
|
426
428
|
variant: "info",
|
|
427
429
|
value: $.value.value,
|
|
428
430
|
detail: $.value.claim_set_label ?? "Reference output",
|
|
429
431
|
accept: a.save ? () => {
|
|
430
|
-
var
|
|
431
|
-
return ne(pe((
|
|
432
|
+
var u;
|
|
433
|
+
return ne(pe((u = $.value) == null ? void 0 : u.value), "claim");
|
|
432
434
|
} : void 0,
|
|
433
|
-
winner:
|
|
434
|
-
}),
|
|
435
|
+
winner: n.value.source === "claim"
|
|
436
|
+
}), v;
|
|
435
437
|
}), B = U(""), Y = U(!1);
|
|
436
|
-
async function ne(
|
|
438
|
+
async function ne(v, u) {
|
|
437
439
|
if (!(!a.save || Y.value)) {
|
|
438
440
|
Y.value = !0;
|
|
439
441
|
try {
|
|
440
|
-
const C = await a.save(
|
|
441
|
-
g("saved", C),
|
|
442
|
+
const C = await a.save(v, u);
|
|
443
|
+
g("saved", C), s.success(`Verified — ${j.value} locked in`);
|
|
442
444
|
} catch {
|
|
443
|
-
|
|
445
|
+
s.danger(`Could not save ${j.value} — try again`);
|
|
444
446
|
} finally {
|
|
445
447
|
Y.value = !1;
|
|
446
448
|
}
|
|
447
449
|
}
|
|
448
450
|
}
|
|
449
451
|
const Ie = () => ne(B.value, "custom");
|
|
450
|
-
function pe(
|
|
451
|
-
return
|
|
452
|
+
function pe(v) {
|
|
453
|
+
return v == null ? null : String(v);
|
|
452
454
|
}
|
|
453
|
-
function me(
|
|
454
|
-
return
|
|
455
|
+
function me(v) {
|
|
456
|
+
return v == null ? "—" : String(v);
|
|
455
457
|
}
|
|
456
458
|
const F = U(null), Z = U(!1), ee = U(null);
|
|
457
459
|
return ce(
|
|
458
|
-
[E,
|
|
459
|
-
async ([
|
|
460
|
-
if (!(
|
|
460
|
+
[E, f],
|
|
461
|
+
async ([v, u]) => {
|
|
462
|
+
if (!(v !== "audit" || !u || F.value !== null || Z.value) && m.auditUrl) {
|
|
461
463
|
Z.value = !0, ee.value = null;
|
|
462
464
|
try {
|
|
463
465
|
F.value = await lt(
|
|
464
|
-
|
|
466
|
+
m.auditUrl,
|
|
465
467
|
a.meta.anchor
|
|
466
468
|
);
|
|
467
469
|
} catch (C) {
|
|
@@ -472,34 +474,34 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
472
474
|
}
|
|
473
475
|
},
|
|
474
476
|
{ immediate: !0 }
|
|
475
|
-
), (
|
|
476
|
-
V(
|
|
477
|
-
modelValue:
|
|
478
|
-
"onUpdate:modelValue":
|
|
477
|
+
), (v, u) => (l(), o(L, null, [
|
|
478
|
+
V(i(re), {
|
|
479
|
+
modelValue: f.value,
|
|
480
|
+
"onUpdate:modelValue": u[3] || (u[3] = (C) => f.value = C),
|
|
479
481
|
title: j.value,
|
|
480
482
|
width: 90,
|
|
481
483
|
height: 90,
|
|
482
484
|
"close-x": "",
|
|
483
|
-
class: A(
|
|
485
|
+
class: A(i(P))
|
|
484
486
|
}, {
|
|
485
487
|
default: I(() => {
|
|
486
488
|
var C;
|
|
487
489
|
return [
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
490
|
+
r("div", pt, [
|
|
491
|
+
r("section", mt, [
|
|
492
|
+
r("div", gt, [
|
|
493
|
+
r("div", xt, [
|
|
494
|
+
u[6] || (u[6] = r("div", { class: "text-[11px] font-semibold uppercase tracking-wider text-gray-400" }, " Resolved value ", -1)),
|
|
495
|
+
r("div", yt, y(me(n.value.value)), 1),
|
|
496
|
+
r("div", bt, [
|
|
497
|
+
u[5] || (u[5] = T(" source of truth: ", -1)),
|
|
498
|
+
r("span", ht, y(n.value.source), 1)
|
|
497
499
|
])
|
|
498
500
|
]),
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
x.value != null ? (l(), N(
|
|
501
|
+
r("div", _t, [
|
|
502
|
+
u[7] || (u[7] = r("div", { class: "text-[11px] font-semibold uppercase tracking-wider text-gray-400" }, " Extraction confidence ", -1)),
|
|
503
|
+
r("div", wt, [
|
|
504
|
+
x.value != null ? (l(), N(i(we), {
|
|
503
505
|
key: 0,
|
|
504
506
|
value: x.value,
|
|
505
507
|
max: 5,
|
|
@@ -510,65 +512,65 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
510
512
|
"show-text": "",
|
|
511
513
|
"text-position": "beside",
|
|
512
514
|
label: `${x.value}/5`
|
|
513
|
-
}, null, 8, ["value", "variant", "label"])) : (l(),
|
|
515
|
+
}, null, 8, ["value", "variant", "label"])) : (l(), o("div", kt, " No confidence recorded "))
|
|
514
516
|
]),
|
|
515
|
-
|
|
517
|
+
r("div", {
|
|
516
518
|
class: A(["tv-confidence-label mt-1 text-right text-xs font-medium", {
|
|
517
519
|
"text-green-600": k.value === "high",
|
|
518
520
|
"text-yellow-600": k.value === "medium",
|
|
519
521
|
"text-red-600": k.value === "low",
|
|
520
522
|
"text-gray-400": k.value === "unverifiable"
|
|
521
523
|
}])
|
|
522
|
-
}, y(
|
|
524
|
+
}, y(i(ae)[k.value]), 3)
|
|
523
525
|
])
|
|
524
526
|
]),
|
|
525
|
-
e.meta.discrepancy ? (l(), N(
|
|
527
|
+
e.meta.discrepancy ? (l(), N(i(ye), {
|
|
526
528
|
key: 0,
|
|
527
529
|
variant: "warning",
|
|
528
530
|
class: "tv-discrepancy"
|
|
529
531
|
}, {
|
|
530
|
-
default: I(() => [...
|
|
532
|
+
default: I(() => [...u[8] || (u[8] = [
|
|
531
533
|
T(" Sources disagree on this value — review the candidates and pick a winner. ", -1)
|
|
532
534
|
])]),
|
|
533
535
|
_: 1
|
|
534
536
|
})) : _("", !0)
|
|
535
537
|
]),
|
|
536
|
-
V(
|
|
538
|
+
V(i(Le), {
|
|
537
539
|
modelValue: E.value,
|
|
538
|
-
"onUpdate:modelValue":
|
|
540
|
+
"onUpdate:modelValue": u[0] || (u[0] = (c) => E.value = c),
|
|
539
541
|
tabs: X.value,
|
|
540
542
|
class: "tv-modal-tabs"
|
|
541
543
|
}, null, 8, ["modelValue", "tabs"]),
|
|
542
|
-
E.value === "evidence" ? (l(),
|
|
543
|
-
S.value ? (l(),
|
|
544
|
-
|
|
545
|
-
V(
|
|
544
|
+
E.value === "evidence" ? (l(), o("section", $t, [
|
|
545
|
+
S.value ? (l(), o("div", St, [
|
|
546
|
+
u[9] || (u[9] = r("div", { class: "mb-1 text-[11px] font-semibold uppercase tracking-wider text-gray-400" }, " Reasoning ", -1)),
|
|
547
|
+
V(i(je), {
|
|
546
548
|
"model-value": S.value,
|
|
547
549
|
readonly: "",
|
|
548
550
|
class: "tv-reasoning"
|
|
549
551
|
}, null, 8, ["model-value"])
|
|
550
552
|
])) : _("", !0),
|
|
551
|
-
R.value ? (l(),
|
|
553
|
+
R.value ? (l(), o("blockquote", Ct, [
|
|
552
554
|
T(" “" + y(R.value) + "” ", 1),
|
|
553
|
-
V(
|
|
555
|
+
V(i(J), {
|
|
554
556
|
variant: (C = b.value) != null && C.cited_text_verified ? "success" : "muted",
|
|
555
557
|
size: "xxs",
|
|
556
558
|
class: "tv-cited-verified ml-2 not-italic"
|
|
557
559
|
}, {
|
|
558
560
|
default: I(() => {
|
|
559
|
-
var
|
|
561
|
+
var c;
|
|
560
562
|
return [
|
|
561
|
-
T(y((
|
|
563
|
+
T(y((c = b.value) != null && c.cited_text_verified ? "✔ verified in source" : "unverified"), 1)
|
|
562
564
|
];
|
|
563
565
|
}),
|
|
564
566
|
_: 1
|
|
565
567
|
}, 8, ["variant"])
|
|
566
568
|
])) : _("", !0),
|
|
567
|
-
q.value.length ? (l(),
|
|
568
|
-
V(
|
|
569
|
+
q.value.length ? (l(), o("div", Vt, [
|
|
570
|
+
V(i(be), {
|
|
569
571
|
file: q.value[0],
|
|
570
572
|
"file-in-preview": p.value,
|
|
571
|
-
"onUpdate:fileInPreview":
|
|
573
|
+
"onUpdate:fileInPreview": u[1] || (u[1] = (c) => p.value = c),
|
|
572
574
|
"related-files": q.value,
|
|
573
575
|
"layout-toggles": ["sidebar", "continuous"],
|
|
574
576
|
"default-sidebar": "",
|
|
@@ -576,84 +578,84 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
576
578
|
"storage-key": "tv-evidence-viewer",
|
|
577
579
|
class: "h-full min-h-0 flex-1"
|
|
578
580
|
}, null, 8, ["file", "file-in-preview", "related-files"]),
|
|
579
|
-
w.value ? (l(),
|
|
580
|
-
])) : (l(),
|
|
581
|
-
D.value.length ? (l(),
|
|
582
|
-
|
|
583
|
-
(l(!0),
|
|
584
|
-
key: String(
|
|
581
|
+
w.value ? (l(), o("div", Dt, y(w.value), 1)) : _("", !0)
|
|
582
|
+
])) : (l(), o("div", Ot, " No source pages recorded for this data point ")),
|
|
583
|
+
D.value.length ? (l(), o("div", It, [
|
|
584
|
+
u[10] || (u[10] = r("span", { class: "text-[11px] font-semibold uppercase tracking-wider text-gray-400" }, "Full documents:", -1)),
|
|
585
|
+
(l(!0), o(L, null, M(D.value, (c) => (l(), N(i(se), {
|
|
586
|
+
key: String(c.id),
|
|
585
587
|
size: "sm",
|
|
586
588
|
variant: "info",
|
|
587
589
|
class: "tv-open-document",
|
|
588
|
-
onClick: (xa) => z.value =
|
|
590
|
+
onClick: (xa) => z.value = c
|
|
589
591
|
}, {
|
|
590
592
|
default: I(() => [
|
|
591
|
-
T(y(
|
|
593
|
+
T(y(c.name), 1)
|
|
592
594
|
]),
|
|
593
595
|
_: 2
|
|
594
596
|
}, 1032, ["onClick"]))), 128))
|
|
595
597
|
])) : _("", !0)
|
|
596
598
|
])) : _("", !0),
|
|
597
|
-
E.value === "candidates" ? (l(),
|
|
598
|
-
(l(!0),
|
|
599
|
-
key:
|
|
599
|
+
E.value === "candidates" ? (l(), o("section", Tt, [
|
|
600
|
+
(l(!0), o(L, null, M(Q.value, (c) => (l(), o("div", {
|
|
601
|
+
key: c.key,
|
|
600
602
|
class: A(["tv-candidate-row rounded-lg border p-4 transition-shadow", [
|
|
601
|
-
|
|
602
|
-
e.meta.discrepancy && !
|
|
603
|
+
c.winner ? "border-gray-300 bg-gray-50 shadow-sm" : "border-gray-200",
|
|
604
|
+
e.meta.discrepancy && !c.winner ? "tv-candidate-disagrees border-amber-200" : ""
|
|
603
605
|
]])
|
|
604
606
|
}, [
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
V(
|
|
609
|
-
variant:
|
|
607
|
+
r("div", Ut, [
|
|
608
|
+
r("div", Nt, [
|
|
609
|
+
r("div", At, [
|
|
610
|
+
V(i(J), {
|
|
611
|
+
variant: c.variant,
|
|
610
612
|
size: "xs"
|
|
611
613
|
}, {
|
|
612
614
|
default: I(() => [
|
|
613
|
-
T(y(
|
|
615
|
+
T(y(c.title), 1)
|
|
614
616
|
]),
|
|
615
617
|
_: 2
|
|
616
618
|
}, 1032, ["variant"]),
|
|
617
|
-
|
|
619
|
+
c.winner ? (l(), N(i(J), {
|
|
618
620
|
key: 0,
|
|
619
621
|
variant: "success",
|
|
620
622
|
size: "xxs",
|
|
621
623
|
class: "tv-winner-chip"
|
|
622
624
|
}, {
|
|
623
|
-
default: I(() => [...
|
|
625
|
+
default: I(() => [...u[11] || (u[11] = [
|
|
624
626
|
T("current value", -1)
|
|
625
627
|
])]),
|
|
626
628
|
_: 1
|
|
627
629
|
})) : _("", !0)
|
|
628
630
|
]),
|
|
629
|
-
|
|
630
|
-
|
|
631
|
+
r("div", Rt, y(me(c.value)), 1),
|
|
632
|
+
r("div", Lt, y(c.detail), 1)
|
|
631
633
|
]),
|
|
632
|
-
|
|
634
|
+
c.accept && !c.winner ? (l(), N(i(se), {
|
|
633
635
|
key: 0,
|
|
634
636
|
size: "sm",
|
|
635
|
-
variant:
|
|
637
|
+
variant: c.variant,
|
|
636
638
|
loading: Y.value,
|
|
637
|
-
class: A(`tv-accept-${
|
|
638
|
-
onClick:
|
|
639
|
+
class: A(`tv-accept-${c.key}`),
|
|
640
|
+
onClick: c.accept
|
|
639
641
|
}, {
|
|
640
|
-
default: I(() => [...
|
|
642
|
+
default: I(() => [...u[12] || (u[12] = [
|
|
641
643
|
T("Accept this value", -1)
|
|
642
644
|
])]),
|
|
643
645
|
_: 1
|
|
644
646
|
}, 8, ["variant", "loading", "class", "onClick"])) : _("", !0)
|
|
645
647
|
])
|
|
646
648
|
], 2))), 128)),
|
|
647
|
-
e.save ? (l(),
|
|
648
|
-
V(
|
|
649
|
+
e.save ? (l(), o("div", jt, [
|
|
650
|
+
V(i(Ee), {
|
|
649
651
|
modelValue: B.value,
|
|
650
|
-
"onUpdate:modelValue":
|
|
652
|
+
"onUpdate:modelValue": u[2] || (u[2] = (c) => B.value = c),
|
|
651
653
|
size: "sm",
|
|
652
654
|
class: "tv-custom-input flex-1",
|
|
653
655
|
placeholder: "Type the correct value…",
|
|
654
656
|
disabled: Y.value
|
|
655
657
|
}, null, 8, ["modelValue", "disabled"]),
|
|
656
|
-
V(
|
|
658
|
+
V(i(se), {
|
|
657
659
|
variant: "success",
|
|
658
660
|
size: "sm",
|
|
659
661
|
class: "tv-accept-custom",
|
|
@@ -661,19 +663,19 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
661
663
|
disabled: !B.value,
|
|
662
664
|
onClick: Ie
|
|
663
665
|
}, {
|
|
664
|
-
default: I(() => [...
|
|
666
|
+
default: I(() => [...u[13] || (u[13] = [
|
|
665
667
|
T("Save custom value", -1)
|
|
666
668
|
])]),
|
|
667
669
|
_: 1
|
|
668
670
|
}, 8, ["loading", "disabled"])
|
|
669
|
-
])) : (l(),
|
|
671
|
+
])) : (l(), o("div", Et, " Read-only render — corrections are disabled here "))
|
|
670
672
|
])) : _("", !0),
|
|
671
|
-
E.value === "audit" ? (l(),
|
|
672
|
-
Z.value ? (l(),
|
|
673
|
-
key:
|
|
673
|
+
E.value === "audit" ? (l(), o("section", zt, [
|
|
674
|
+
Z.value ? (l(), o(L, { key: 0 }, M(2, (c) => V(i(ze), {
|
|
675
|
+
key: c,
|
|
674
676
|
shape: "rounded",
|
|
675
677
|
class: "tv-audit-skeleton h-24 w-full"
|
|
676
|
-
})), 64)) : ee.value ? (l(), N(
|
|
678
|
+
})), 64)) : ee.value ? (l(), N(i(ye), {
|
|
677
679
|
key: 1,
|
|
678
680
|
variant: "danger",
|
|
679
681
|
class: "tv-audit-error"
|
|
@@ -682,9 +684,9 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
682
684
|
T(" Could not load the audit trail: " + y(ee.value), 1)
|
|
683
685
|
]),
|
|
684
686
|
_: 1
|
|
685
|
-
})) : F.value && F.value.length === 0 ? (l(),
|
|
686
|
-
key: String(
|
|
687
|
-
call:
|
|
687
|
+
})) : F.value && F.value.length === 0 ? (l(), o("div", Pt, " No LLM calls recorded for this data point ")) : F.value ? (l(!0), o(L, { key: 3 }, M(F.value, (c) => (l(), N(ft, {
|
|
688
|
+
key: String(c.id),
|
|
689
|
+
call: c
|
|
688
690
|
}, null, 8, ["call"]))), 128)) : _("", !0)
|
|
689
691
|
])) : _("", !0)
|
|
690
692
|
])
|
|
@@ -692,18 +694,18 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
692
694
|
}),
|
|
693
695
|
_: 1
|
|
694
696
|
}, 8, ["modelValue", "title", "class"]),
|
|
695
|
-
z.value ? (l(), N(
|
|
697
|
+
z.value ? (l(), N(i(re), {
|
|
696
698
|
key: 0,
|
|
697
699
|
modelValue: G.value,
|
|
698
|
-
"onUpdate:modelValue":
|
|
700
|
+
"onUpdate:modelValue": u[4] || (u[4] = (C) => G.value = C),
|
|
699
701
|
title: z.value.name,
|
|
700
702
|
width: 90,
|
|
701
703
|
height: 90,
|
|
702
704
|
"close-x": "",
|
|
703
|
-
class: A(
|
|
705
|
+
class: A(i(P))
|
|
704
706
|
}, {
|
|
705
707
|
default: I(() => [
|
|
706
|
-
V(
|
|
708
|
+
V(i(be), {
|
|
707
709
|
file: z.value,
|
|
708
710
|
downloadable: "",
|
|
709
711
|
zoomable: "",
|
|
@@ -731,33 +733,33 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
731
733
|
format: { type: Function }
|
|
732
734
|
},
|
|
733
735
|
setup(e) {
|
|
734
|
-
const t = e, a = le(), g =
|
|
736
|
+
const t = e, a = le(), g = d(() => a.enabled.value), m = U(null), s = d(() => {
|
|
735
737
|
var p;
|
|
736
|
-
return
|
|
737
|
-
}),
|
|
738
|
+
return m.value ? m.value : t.source && t.field ? ((p = t.source.__meta) == null ? void 0 : p[t.field]) ?? null : null;
|
|
739
|
+
}), f = d(() => fe(s.value)), n = d(() => {
|
|
738
740
|
if (t.original !== void 0 && t.original !== null)
|
|
739
741
|
return t.original;
|
|
740
|
-
if (
|
|
741
|
-
return
|
|
742
|
+
if (s.value && f.value.value !== null && f.value.value !== void 0)
|
|
743
|
+
return f.value.value;
|
|
742
744
|
if (t.source && t.field) return t.source[t.field];
|
|
743
|
-
}), b =
|
|
744
|
-
const p =
|
|
745
|
-
return p == null ? "" : t.format ? t.format(p) : String(p);
|
|
746
|
-
}), $ =
|
|
745
|
+
}), b = d(() => {
|
|
746
|
+
const p = n.value;
|
|
747
|
+
return p == null ? "" : typeof t.format == "function" ? t.format(p) : String(p);
|
|
748
|
+
}), $ = d(
|
|
747
749
|
() => {
|
|
748
750
|
var p, w, D;
|
|
749
|
-
return ve((D = (w = (p =
|
|
751
|
+
return ve((D = (w = (p = s.value) == null ? void 0 : p.candidates) == null ? void 0 : w.extracted) == null ? void 0 : D.confidence);
|
|
750
752
|
}
|
|
751
|
-
), h =
|
|
753
|
+
), h = d(() => Ve(s.value)), x = d(() => {
|
|
752
754
|
var p, w;
|
|
753
|
-
return !!((w = (p =
|
|
754
|
-
}), k =
|
|
755
|
+
return !!((w = (p = s.value) == null ? void 0 : p.candidates) != null && w.override);
|
|
756
|
+
}), k = d(() => {
|
|
755
757
|
var w;
|
|
756
|
-
const p = (w =
|
|
758
|
+
const p = (w = s.value) == null ? void 0 : w.candidates;
|
|
757
759
|
return !!(p != null && p.override || p != null && p.extracted || p != null && p.claim);
|
|
758
|
-
}), S =
|
|
760
|
+
}), S = d(() => g.value && !!s.value), R = d(() => {
|
|
759
761
|
var G, Q, B;
|
|
760
|
-
const p = (Q = (G =
|
|
762
|
+
const p = (Q = (G = s.value) == null ? void 0 : G.candidates) == null ? void 0 : Q.extracted;
|
|
761
763
|
if (!p) return "No verification data";
|
|
762
764
|
const w = [], D = ae[$.value];
|
|
763
765
|
w.push(
|
|
@@ -768,19 +770,19 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
768
770
|
});
|
|
769
771
|
function O(p) {
|
|
770
772
|
var w;
|
|
771
|
-
|
|
773
|
+
m.value = p, (w = t.source) != null && w.__meta && t.field && (t.source.__meta[t.field] = p);
|
|
772
774
|
}
|
|
773
|
-
const j =
|
|
775
|
+
const j = d(() => Ze(a, s, O)), H = d(() => !!j.value), E = U(!1), W = U(!1);
|
|
774
776
|
function X() {
|
|
775
|
-
|
|
777
|
+
s.value && (E.value = !0);
|
|
776
778
|
}
|
|
777
779
|
async function q(p) {
|
|
778
780
|
W.value = !1;
|
|
779
781
|
const D = (p.target.textContent ?? "").trim();
|
|
780
782
|
!j.value || D === b.value || await j.value(D, "custom");
|
|
781
783
|
}
|
|
782
|
-
return (p, w) => (l(),
|
|
783
|
-
|
|
784
|
+
return (p, w) => (l(), o("span", Bt, [
|
|
785
|
+
r("span", {
|
|
784
786
|
class: A([
|
|
785
787
|
"tv-field-value",
|
|
786
788
|
S.value && !k.value ? "tv-field-unverified cursor-pointer border-b border-dotted border-gray-300" : ""
|
|
@@ -793,37 +795,37 @@ const it = { class: "tv-audit-call rounded-lg border border-gray-200 shadow-sm"
|
|
|
793
795
|
onClick: w[2] || (w[2] = (D) => S.value && !k.value ? X() : void 0)
|
|
794
796
|
}, [
|
|
795
797
|
Ne(p.$slots, "default", {
|
|
796
|
-
value:
|
|
798
|
+
value: n.value,
|
|
797
799
|
formatted: b.value
|
|
798
800
|
}, () => [
|
|
799
801
|
T(y(b.value), 1)
|
|
800
802
|
])
|
|
801
803
|
], 42, Ft),
|
|
802
|
-
S.value && k.value ? (l(), N(
|
|
804
|
+
S.value && k.value ? (l(), N(i(Pe), {
|
|
803
805
|
key: 0,
|
|
804
806
|
tooltip: R.value,
|
|
805
807
|
placement: "top"
|
|
806
808
|
}, {
|
|
807
809
|
trigger: I(() => [
|
|
808
|
-
|
|
810
|
+
r("button", {
|
|
809
811
|
type: "button",
|
|
810
|
-
class: A(["tv-overlay inline-flex cursor-pointer items-center align-middle transition-transform duration-150 hover:scale-110",
|
|
812
|
+
class: A(["tv-overlay inline-flex cursor-pointer items-center align-middle transition-transform duration-150 hover:scale-110", i(P)]),
|
|
811
813
|
onClick: X
|
|
812
814
|
}, [
|
|
813
|
-
x.value ? (l(),
|
|
815
|
+
x.value ? (l(), o("span", qt, "✔")) : (l(), N(ue, {
|
|
814
816
|
key: 0,
|
|
815
817
|
status: $.value
|
|
816
818
|
}, null, 8, ["status"])),
|
|
817
|
-
h.value && !x.value ? (l(),
|
|
819
|
+
h.value && !x.value ? (l(), o("span", Yt, "⚠")) : _("", !0)
|
|
818
820
|
], 2)
|
|
819
821
|
]),
|
|
820
822
|
_: 1
|
|
821
823
|
}, 8, ["tooltip"])) : _("", !0),
|
|
822
|
-
|
|
824
|
+
s.value ? (l(), N(Mt, {
|
|
823
825
|
key: 1,
|
|
824
826
|
modelValue: E.value,
|
|
825
827
|
"onUpdate:modelValue": w[3] || (w[3] = (D) => E.value = D),
|
|
826
|
-
meta:
|
|
828
|
+
meta: s.value,
|
|
827
829
|
label: e.field,
|
|
828
830
|
save: j.value
|
|
829
831
|
}, null, 8, ["modelValue", "meta", "label", "save"])) : _("", !0)
|
|
@@ -836,24 +838,24 @@ function Oe(e, t = "") {
|
|
|
836
838
|
}
|
|
837
839
|
function de(e, t, a) {
|
|
838
840
|
if (Array.isArray(e)) {
|
|
839
|
-
e.forEach((
|
|
841
|
+
e.forEach((s, f) => de(s, `${t}[${f}]`, a));
|
|
840
842
|
return;
|
|
841
843
|
}
|
|
842
844
|
if (!he(e)) return;
|
|
843
|
-
const
|
|
844
|
-
for (const [
|
|
845
|
-
if (
|
|
846
|
-
const
|
|
847
|
-
if (Array.isArray(
|
|
848
|
-
de(
|
|
845
|
+
const m = e.__meta ?? {};
|
|
846
|
+
for (const [s, f] of Object.entries(e)) {
|
|
847
|
+
if (s === "__meta") continue;
|
|
848
|
+
const n = t ? `${t}.${s}` : s;
|
|
849
|
+
if (Array.isArray(f) || he(f)) {
|
|
850
|
+
de(f, n, a);
|
|
849
851
|
continue;
|
|
850
852
|
}
|
|
851
|
-
const b =
|
|
852
|
-
!b && Jt.has(
|
|
853
|
-
path:
|
|
854
|
-
label:
|
|
853
|
+
const b = m[s];
|
|
854
|
+
!b && Jt.has(s) || a.push({
|
|
855
|
+
path: n,
|
|
856
|
+
label: s,
|
|
855
857
|
meta: b ?? null,
|
|
856
|
-
value:
|
|
858
|
+
value: f,
|
|
857
859
|
unanchored: !b
|
|
858
860
|
});
|
|
859
861
|
}
|
|
@@ -862,23 +864,23 @@ function he(e) {
|
|
|
862
864
|
return typeof e == "object" && e !== null && !Array.isArray(e);
|
|
863
865
|
}
|
|
864
866
|
function Kt(e) {
|
|
865
|
-
var
|
|
867
|
+
var s;
|
|
866
868
|
const t = Oe(e).filter(
|
|
867
|
-
(
|
|
869
|
+
(f) => f.meta !== null
|
|
868
870
|
), a = t.length;
|
|
869
|
-
let g = 0,
|
|
870
|
-
for (const
|
|
871
|
-
if (
|
|
871
|
+
let g = 0, m = 0;
|
|
872
|
+
for (const f of t) {
|
|
873
|
+
if (f.meta.candidates.override) {
|
|
872
874
|
g++;
|
|
873
875
|
continue;
|
|
874
876
|
}
|
|
875
|
-
const
|
|
876
|
-
(
|
|
877
|
+
const n = (s = f.meta.candidates.extracted) == null ? void 0 : s.confidence;
|
|
878
|
+
(f.meta.discrepancy || n == null || n <= 2) && m++;
|
|
877
879
|
}
|
|
878
880
|
return {
|
|
879
881
|
total: a,
|
|
880
882
|
verified: g,
|
|
881
|
-
needsReview:
|
|
883
|
+
needsReview: m,
|
|
882
884
|
percent: a === 0 ? 100 : Math.round(g / a * 100)
|
|
883
885
|
};
|
|
884
886
|
}
|
|
@@ -903,15 +905,15 @@ const Ht = { class: "tv-comparison-page flex flex-col gap-4" }, Gt = {
|
|
|
903
905
|
}, da = { class: "tv-datapoint-path font-mono text-xs text-gray-500" }, ca = { class: "tv-datapoint-value" }, va = /* @__PURE__ */ K({
|
|
904
906
|
__name: "ComparisonPage",
|
|
905
907
|
setup(e) {
|
|
906
|
-
const t = le(), a =
|
|
907
|
-
function
|
|
908
|
+
const t = le(), a = d(() => Oe(t.data)), g = d(() => a.value.filter(($) => !$.unanchored)), m = d(() => a.value.filter(($) => $.unanchored));
|
|
909
|
+
function s($) {
|
|
908
910
|
const h = fe($).value;
|
|
909
911
|
return h == null ? "" : String(h);
|
|
910
912
|
}
|
|
911
|
-
function
|
|
913
|
+
function f($) {
|
|
912
914
|
return $ == null ? "" : String($);
|
|
913
915
|
}
|
|
914
|
-
function
|
|
916
|
+
function n($) {
|
|
915
917
|
var h, x, k;
|
|
916
918
|
return (k = (x = (h = $.meta) == null ? void 0 : h.candidates) == null ? void 0 : x.extracted) == null ? void 0 : k.confidence;
|
|
917
919
|
}
|
|
@@ -922,62 +924,62 @@ const Ht = { class: "tv-comparison-page flex flex-col gap-4" }, Gt = {
|
|
|
922
924
|
const x = [];
|
|
923
925
|
return h.override && x.push({ source: "override", value: h.override.value }), h.extracted && x.push({ source: "extracted", value: h.extracted.value }), h.claim && x.push({ source: "claim", value: h.claim.value }), x;
|
|
924
926
|
}
|
|
925
|
-
return ($, h) => (l(),
|
|
926
|
-
h[1] || (h[1] =
|
|
927
|
-
a.value.length === 0 ? (l(),
|
|
928
|
-
g.value.length ? (l(),
|
|
929
|
-
(l(!0),
|
|
927
|
+
return ($, h) => (l(), o("div", Ht, [
|
|
928
|
+
h[1] || (h[1] = r("h2", { class: "tv-comparison-title text-lg font-semibold" }, "Verification comparison", -1)),
|
|
929
|
+
a.value.length === 0 ? (l(), o("p", Gt, " No data points to compare. ")) : _("", !0),
|
|
930
|
+
g.value.length ? (l(), o("section", Qt, [
|
|
931
|
+
(l(!0), o(L, null, M(g.value, (x) => {
|
|
930
932
|
var k, S, R;
|
|
931
|
-
return l(),
|
|
933
|
+
return l(), o("div", {
|
|
932
934
|
key: x.path,
|
|
933
935
|
class: "tv-datapoint border-t border-gray-100 pt-2"
|
|
934
936
|
}, [
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
937
|
+
r("div", Wt, [
|
|
938
|
+
r("span", Xt, y(x.path), 1),
|
|
939
|
+
r("span", Zt, y(s(x.meta)), 1),
|
|
938
940
|
V(ue, {
|
|
939
|
-
confidence:
|
|
941
|
+
confidence: n(x),
|
|
940
942
|
"show-label": ""
|
|
941
943
|
}, null, 8, ["confidence"]),
|
|
942
|
-
|
|
944
|
+
i(Ve)(x.meta) ? (l(), o("span", ea, "⚠ discrepancy")) : _("", !0)
|
|
943
945
|
]),
|
|
944
|
-
|
|
945
|
-
(l(!0),
|
|
946
|
+
r("ul", ta, [
|
|
947
|
+
(l(!0), o(L, null, M(b(x), (O) => (l(), o("li", {
|
|
946
948
|
key: O.source,
|
|
947
949
|
class: "tv-candidate"
|
|
948
950
|
}, [
|
|
949
|
-
|
|
950
|
-
T(" " + y(
|
|
951
|
+
r("span", aa, y(O.source) + ":", 1),
|
|
952
|
+
T(" " + y(f(O.value)), 1)
|
|
951
953
|
]))), 128))
|
|
952
954
|
]),
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
(l(!0),
|
|
955
|
+
i(ie)(x.meta) ? (l(), o("p", la, y(i(ie)(x.meta)), 1)) : _("", !0),
|
|
956
|
+
i(oe)(x.meta) ? (l(), o("p", na, " “" + y(i(oe)(x.meta)) + "” ", 1)) : _("", !0),
|
|
957
|
+
r("ul", sa, [
|
|
958
|
+
(l(!0), o(L, null, M(i(De)((R = (S = (k = x.meta) == null ? void 0 : k.candidates) == null ? void 0 : S.extracted) == null ? void 0 : R.sources), (O, j) => (l(), o("li", {
|
|
957
959
|
key: j,
|
|
958
960
|
class: "tv-source-group"
|
|
959
961
|
}, [
|
|
960
|
-
O.fileUrl ? (l(),
|
|
962
|
+
O.fileUrl ? (l(), o("a", {
|
|
961
963
|
key: 0,
|
|
962
964
|
href: O.fileUrl,
|
|
963
965
|
class: "tv-source-link text-blue-600 underline",
|
|
964
966
|
target: "_blank",
|
|
965
967
|
rel: "noopener"
|
|
966
|
-
}, y(O.fileLabel), 9, ra)) : (l(),
|
|
967
|
-
|
|
968
|
+
}, y(O.fileLabel), 9, ra)) : (l(), o("span", ia, y(O.fileLabel), 1)),
|
|
969
|
+
r("span", oa, "(" + y(O.sources.map(i(rt)).join(", ")) + ")", 1)
|
|
968
970
|
]))), 128))
|
|
969
971
|
])
|
|
970
972
|
]);
|
|
971
973
|
}), 128))
|
|
972
974
|
])) : _("", !0),
|
|
973
|
-
|
|
974
|
-
h[0] || (h[0] =
|
|
975
|
-
(l(!0),
|
|
975
|
+
m.value.length ? (l(), o("section", ua, [
|
|
976
|
+
h[0] || (h[0] = r("h3", { class: "tv-unanchored-title text-sm font-semibold text-gray-500" }, " Unanchored / not from source ", -1)),
|
|
977
|
+
(l(!0), o(L, null, M(m.value, (x) => (l(), o("div", {
|
|
976
978
|
key: x.path,
|
|
977
979
|
class: "tv-unanchored-datapoint flex items-center gap-2 text-sm"
|
|
978
980
|
}, [
|
|
979
|
-
|
|
980
|
-
|
|
981
|
+
r("span", da, y(x.path), 1),
|
|
982
|
+
r("span", ca, y(f(x.value)), 1),
|
|
981
983
|
V(ue, { status: "unverifiable" })
|
|
982
984
|
]))), 128))
|
|
983
985
|
])) : _("", !0)
|
|
@@ -986,11 +988,11 @@ const Ht = { class: "tv-comparison-page flex flex-col gap-4" }, Gt = {
|
|
|
986
988
|
}), fa = { class: "tv-enable-toggle flex items-center justify-between text-sm font-medium text-gray-700" }, pa = { class: "tv-progress-block" }, ma = { class: "mb-1 flex items-baseline justify-between" }, ga = { class: "tv-progress-count text-xs font-semibold text-gray-600" }, wa = /* @__PURE__ */ K({
|
|
987
989
|
__name: "VerificationChrome",
|
|
988
990
|
setup(e) {
|
|
989
|
-
const t = le(), { enabled: a, openComparison: g } = t,
|
|
991
|
+
const t = le(), { enabled: a, openComparison: g } = t, m = He(), s = _e(), f = U(!1), n = d(() => Kt(t.data)), b = U(!1);
|
|
990
992
|
ce(
|
|
991
|
-
() =>
|
|
993
|
+
() => n.value.percent,
|
|
992
994
|
(k) => {
|
|
993
|
-
k === 100 &&
|
|
995
|
+
k === 100 && n.value.total > 0 && !b.value && (b.value = !0, s.success("All data points verified 🎯"));
|
|
994
996
|
}
|
|
995
997
|
);
|
|
996
998
|
let $ = 0;
|
|
@@ -1010,88 +1012,88 @@ const Ht = { class: "tv-comparison-page flex flex-col gap-4" }, Gt = {
|
|
|
1010
1012
|
);
|
|
1011
1013
|
}
|
|
1012
1014
|
function x() {
|
|
1013
|
-
g(),
|
|
1015
|
+
g(), f.value = !1;
|
|
1014
1016
|
}
|
|
1015
|
-
return (k, S) => (l(),
|
|
1016
|
-
|
|
1017
|
+
return (k, S) => (l(), o(L, null, [
|
|
1018
|
+
r("button", {
|
|
1017
1019
|
type: "button",
|
|
1018
|
-
class: A(["tv-settings-button fixed bottom-4 right-4 z-50 flex h-11 w-11 items-center justify-center rounded-full bg-gray-900 text-white shadow-lg transition-transform hover:scale-105",
|
|
1020
|
+
class: A(["tv-settings-button fixed bottom-4 right-4 z-50 flex h-11 w-11 items-center justify-center rounded-full bg-gray-900 text-white shadow-lg transition-transform hover:scale-105", i(P)]),
|
|
1019
1021
|
title: "Verification",
|
|
1020
|
-
onClick: S[0] || (S[0] = (R) =>
|
|
1022
|
+
onClick: S[0] || (S[0] = (R) => f.value = !f.value)
|
|
1021
1023
|
}, [
|
|
1022
|
-
V(
|
|
1023
|
-
icon:
|
|
1024
|
+
V(i(Me), {
|
|
1025
|
+
icon: i(Be),
|
|
1024
1026
|
class: "h-5 w-5"
|
|
1025
1027
|
}, null, 8, ["icon"]),
|
|
1026
|
-
|
|
1028
|
+
i(a) && n.value.needsReview > 0 ? (l(), N(i(Fe), {
|
|
1027
1029
|
key: 0,
|
|
1028
|
-
value:
|
|
1030
|
+
value: n.value.needsReview,
|
|
1029
1031
|
variant: "warning",
|
|
1030
1032
|
class: "tv-needs-review-badge absolute -right-1 -top-1"
|
|
1031
1033
|
}, null, 8, ["value"])) : _("", !0)
|
|
1032
1034
|
], 2),
|
|
1033
|
-
|
|
1035
|
+
f.value ? (l(), o("div", {
|
|
1034
1036
|
key: 0,
|
|
1035
|
-
class: A(["tv-settings-panel fixed bottom-20 right-4 z-50 flex w-72 flex-col gap-4 rounded-xl bg-white p-4 shadow-2xl ring-1 ring-gray-200",
|
|
1037
|
+
class: A(["tv-settings-panel fixed bottom-20 right-4 z-50 flex w-72 flex-col gap-4 rounded-xl bg-white p-4 shadow-2xl ring-1 ring-gray-200", i(P)])
|
|
1036
1038
|
}, [
|
|
1037
|
-
|
|
1038
|
-
S[3] || (S[3] =
|
|
1039
|
-
Ae(
|
|
1039
|
+
r("label", fa, [
|
|
1040
|
+
S[3] || (S[3] = r("span", null, "Verification overlay", -1)),
|
|
1041
|
+
Ae(r("input", {
|
|
1040
1042
|
"onUpdate:modelValue": S[1] || (S[1] = (R) => ge(a) ? a.value = R : null),
|
|
1041
1043
|
type: "checkbox",
|
|
1042
1044
|
class: "tv-enable-checkbox h-4 w-4 accent-gray-900"
|
|
1043
1045
|
}, null, 512), [
|
|
1044
|
-
[Re,
|
|
1046
|
+
[Re, i(a)]
|
|
1045
1047
|
])
|
|
1046
1048
|
]),
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
S[4] || (S[4] =
|
|
1051
|
-
|
|
1049
|
+
i(a) && n.value.total > 0 ? (l(), o(L, { key: 0 }, [
|
|
1050
|
+
r("div", pa, [
|
|
1051
|
+
r("div", ma, [
|
|
1052
|
+
S[4] || (S[4] = r("span", { class: "text-[11px] font-semibold uppercase tracking-wider text-gray-400" }, "Review progress", -1)),
|
|
1053
|
+
r("span", ga, y(n.value.verified) + " / " + y(n.value.total), 1)
|
|
1052
1054
|
]),
|
|
1053
|
-
V(
|
|
1054
|
-
value:
|
|
1055
|
-
max:
|
|
1055
|
+
V(i(we), {
|
|
1056
|
+
value: n.value.verified,
|
|
1057
|
+
max: n.value.total,
|
|
1056
1058
|
size: "md",
|
|
1057
|
-
variant:
|
|
1058
|
-
striped:
|
|
1059
|
-
"animate-stripes":
|
|
1060
|
-
glow:
|
|
1059
|
+
variant: n.value.percent === 100 ? "success" : "info",
|
|
1060
|
+
striped: n.value.percent < 100,
|
|
1061
|
+
"animate-stripes": n.value.percent < 100,
|
|
1062
|
+
glow: n.value.percent === 100,
|
|
1061
1063
|
gradient: ""
|
|
1062
1064
|
}, null, 8, ["value", "max", "variant", "striped", "animate-stripes", "glow"])
|
|
1063
1065
|
]),
|
|
1064
|
-
|
|
1066
|
+
n.value.needsReview > 0 ? (l(), o("button", {
|
|
1065
1067
|
key: 0,
|
|
1066
1068
|
type: "button",
|
|
1067
|
-
class: A(["tv-next-flagged flex items-center justify-between rounded-lg bg-amber-50 px-3 py-2 text-left text-xs font-medium text-amber-700 ring-1 ring-inset ring-amber-600/20 transition hover:bg-amber-100",
|
|
1069
|
+
class: A(["tv-next-flagged flex items-center justify-between rounded-lg bg-amber-50 px-3 py-2 text-left text-xs font-medium text-amber-700 ring-1 ring-inset ring-amber-600/20 transition hover:bg-amber-100", i(P)]),
|
|
1068
1070
|
onClick: h
|
|
1069
1071
|
}, [
|
|
1070
|
-
|
|
1071
|
-
S[5] || (S[5] =
|
|
1072
|
+
r("span", null, y(n.value.needsReview) + " need" + y(n.value.needsReview === 1 ? "s" : "") + " review", 1),
|
|
1073
|
+
S[5] || (S[5] = r("span", { "aria-hidden": "true" }, "→", -1))
|
|
1072
1074
|
], 2)) : _("", !0)
|
|
1073
1075
|
], 64)) : _("", !0),
|
|
1074
|
-
|
|
1076
|
+
r("button", {
|
|
1075
1077
|
type: "button",
|
|
1076
|
-
class: A(["tv-open-comparison rounded-lg border border-gray-200 px-3 py-2 text-sm font-medium text-gray-600 transition hover:bg-gray-50",
|
|
1078
|
+
class: A(["tv-open-comparison rounded-lg border border-gray-200 px-3 py-2 text-sm font-medium text-gray-600 transition hover:bg-gray-50", i(P)]),
|
|
1077
1079
|
onClick: x
|
|
1078
1080
|
}, " Open comparison page ", 2)
|
|
1079
1081
|
], 2)) : _("", !0),
|
|
1080
|
-
V(
|
|
1081
|
-
modelValue:
|
|
1082
|
-
"onUpdate:modelValue": S[2] || (S[2] = (R) => ge(
|
|
1082
|
+
V(i(re), {
|
|
1083
|
+
modelValue: i(m),
|
|
1084
|
+
"onUpdate:modelValue": S[2] || (S[2] = (R) => ge(m) ? m.value = R : null),
|
|
1083
1085
|
title: "Verification comparison",
|
|
1084
1086
|
width: 80,
|
|
1085
1087
|
"close-x": "",
|
|
1086
|
-
class: A(
|
|
1088
|
+
class: A(i(P))
|
|
1087
1089
|
}, {
|
|
1088
1090
|
default: I(() => [
|
|
1089
1091
|
V(va)
|
|
1090
1092
|
]),
|
|
1091
1093
|
_: 1
|
|
1092
1094
|
}, 8, ["modelValue", "class"]),
|
|
1093
|
-
V(
|
|
1094
|
-
class: A(
|
|
1095
|
+
V(i(qe), {
|
|
1096
|
+
class: A(i(P))
|
|
1095
1097
|
}, null, 8, ["class"])
|
|
1096
1098
|
], 64));
|
|
1097
1099
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thehammer/template-verification",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Read-write verification overlay for rendered template apps — per-data-point confidence, discrepancy, 3-source resolution (override > extracted > claim), inline edit, and a recursive comparison page. Consumes the host's __meta sidecar; fetches nothing.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
"engines": {
|
|
26
26
|
"node": ">=18"
|
|
27
27
|
},
|
|
28
|
-
"sideEffects":
|
|
28
|
+
"sideEffects": [
|
|
29
|
+
"**/*.css"
|
|
30
|
+
],
|
|
29
31
|
"scripts": {
|
|
30
32
|
"build": "vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json",
|
|
31
33
|
"test": "vitest run",
|