@thehammer/template-verification
v0.2.10
Published
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.
Readme
@thehammer/template-verification
A read-write verification overlay for rendered template apps. It overlays a trust layer on top of an already-rendered document template: per-data-point confidence pills + verified check chips, discrepancy indicators, and a click-through Inspector dialog — a hero strip (resolved value, gradient confidence meter, discrepancy alert) over three tabs:
- Evidence — readonly-markdown reasoning, cited-text quote, an embedded
DanxFileViewerover the cited source pages, and per-document drill-down to the FULL parent PDF in a stacked dialog. - Candidates — the resolution flow: one card per candidate (override/extracted/claim) with Accept actions + custom-value entry; saves toast and flip the in-document pill to a verified chip.
- Audit trail — the LLM calls behind the data point (model, status,
timing, collapsible JSON request/response), lazy-fetched from the host's
token-sealed
audit_url. Tab hidden when the host mints none.
VerificationChrome adds a review-progress meter (X of Y human-verified),
a needs-review jump button, and completion celebration.
Render data + __meta arrive via a single initVerification() call — the
only network the library touches is the host-supplied saveOverride
transport and the optional auditUrl endpoint. Backend-agnostic and
unit-testable standalone.
Install
npm install @thehammer/template-verificationvue and @thehammer/danx-ui are peer dependencies (runtime externals) — the
host template app already loads both.
Import the stylesheet once (it carries the @media print rule that hides the
overlay chrome on print/export):
import "@thehammer/template-verification/style.css"Usage
Call initVerification() once at your App root (a function call — not a
wrapping element), then drop a single <VerificationChrome/> as a sibling of the
document and use <VerifiedField> anywhere:
<script setup lang="ts">
import { initVerification, VerificationChrome, VerifiedField } from "@thehammer/template-verification"
const props = defineProps<{ data: any }>()
// Host-supplied, authenticated transport. Its presence enables inline editing.
async function saveOverride(args) {
const res = await fetch(`/api/workflow-inputs/${args.workflow_input_id}/data-point-overrides`, {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
body: JSON.stringify({ ...args, object_id: args.object_ids.at(-1) })
})
return res.json() // recomputed DataPointMeta
}
// Once, at root setup. Absent saveOverride ⇒ every field is read-only.
initVerification({
data: props.data,
saveOverride,
workflowInputId: props.data.__verification?.workflow_input_id,
// Token-sealed audit endpoint (optional) — enables the Inspector's Audit tab.
auditUrl: props.data.__verification?.audit_url ?? null
})
</script>
<template>
<article>
<h1><VerifiedField :source="data.claimant" field="full_name" /></h1>
<div v-for="(p, i) in data.medical_providers" :key="i">
<VerifiedField :source="p" field="name" />
</div>
</article>
<!-- Sibling of the document, placed once. -->
<VerificationChrome />
</template>The backing store is a module singleton — safe because each rendered template
runs as its own isolated Vue app inside its own iframe (one JS module instance,
one app-wide config, no SSR). See src/context.ts for the invariant.
The __meta contract
Each rendered object node carries a __meta map keyed by leaf field name. Each
entry is a DataPointMeta:
interface DataPointMeta {
anchor: { object_ids: (number | string)[]; field: string; field_path: string }
candidates: {
override?: { value; source_choice }
extracted?: { value; confidence: number | null; reasoning; cited_text; cited_text_verified; sources[] }
claim?: { value; claim_set_label }
}
discrepancy: boolean
resolved: { value; source: "override" | "extracted" | "claim" | "none" }
}Resolution + status
- Resolution priority:
override > extracted > claim. - Status buckets the integer confidence:
null → unverifiable (gray),≤2 → low (red),==3 → medium (yellow),≥4 → high (green). - Discrepancy is orthogonal to confidence — a high-confidence field can still disagree with a differing claim/override.
Activation
Fully self-contained: a fixed bottom-right settings button toggles the overlay,
persisted to localStorage. No URL flags, no postMessage, no host activation prop.
All library chrome is hidden under print/export media.
Develop
npm test # vitest
npm run build # vite lib build + emitted .d.ts types