Files
justvitamin/scripts/sync-clinically-shown-claims.ts
T
Omair Saleh 056c47581f feat: editorial review dashboard + elite-grade pilot batch (5 SKUs)
Ships the second dashboard surface — a Pattern Library + Preview Theatre — that
presents the 4-section PDP pilot batch back to Umar, compliance, and the board
in an editorial format. Adds the full data layer that drives it: 5 source-backed
per-SKU drafts at QA 100/100, 15 competitor PDP semantic extracts, PubMed
evidence packs, EFSA claims library extension, JV brand voice guide, hand-curated
product FAQs, and the Matrixify-ready CSV exports for Lewis.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 18:50:09 +08:00

139 lines
5.9 KiB
TypeScript

#!/usr/bin/env bun
import { existsSync, readdirSync } from 'fs'
import { join } from 'path'
import { ROOT, readJson, writeJson } from './lib/intel-utils'
const contentRoot = join(ROOT, 'data', 'content')
const productsRoot = join(contentRoot, 'products')
const workflowRoot = join(contentRoot, 'workflow')
const outRoot = join(ROOT, 'content_population_exports')
const metaPath = join(contentRoot, 'metaobjects.json')
const libraryPath = join(ROOT, 'data', 'sources', 'claims', 'claims-library.json')
const now = new Date().toISOString()
function claimRef(handle: string) {
return `clinically_shown_to.${handle}`
}
function asMetaobject(claim: any) {
return {
handle: claim.handle,
name: claim.heading || claim.name_internal || claim.handle,
heading: claim.heading || '',
description: claim.description || '',
stat_1_value: claim.stat_1_value || '',
stat_1_name: claim.stat_1_name || '',
stat_2_value: claim.stat_2_value || '',
stat_2_name: claim.stat_2_name || '',
stat_3_value: claim.stat_3_value || '',
stat_3_name: claim.stat_3_name || '',
disclaimer: claim.disclaimer || '',
citation_title: claim.citation?.source_title || '',
citation_url: claim.citation?.source_url || '',
evidence_type: claim.citation?.evidence_type || '',
approval_owner: claim.approval_owner || '',
approval_date: claim.approval_date || '',
status: 'needs_human_compliance_approval',
source: 'data/sources/claims/claims-library.json'
}
}
const library = readJson(libraryPath, { claims: [] })
const meta = readJson(metaPath, { definitions: {} })
meta.definitions = meta.definitions || {}
meta.definitions.clinically_shown_to = (library.claims || []).map(asMetaobject)
meta.generatedAt = now
writeJson(metaPath, meta)
const rows: any[] = []
let mapped = 0
let unmapped = 0
for (const file of readdirSync(productsRoot).filter(file => file.endsWith('.json')).sort()) {
const path = join(productsRoot, file)
const product = readJson(path, {})
const sku = product.sku || file.replace(/\.json$/, '')
const evidence = readJson(join(ROOT, 'data', 'intelligence', sku, 'claims-evidence.json'), { claims: [] })
const claims = evidence.claims || []
product.metafields = product.metafields || {}
product.approval = product.approval || {}
const previous = product.metafields.pdpClinicallyShownTo || ''
if (claims.length > 0) {
const refs = claims.map((claim: any) => claimRef(claim.handle))
product.metafields.pdpClinicallyShownTo = refs[0]
product.approval.compliance = product.approval.compliance === 'approved'
? 'approved'
: 'needs_human_compliance_approval'
product.notes = Array.isArray(product.notes) ? product.notes : []
const note = 'Mapped source-backed draft clinically_shown_to reference from claims library; final human compliance approval still required.'
if (!product.notes.includes(note)) product.notes.push(note)
mapped += 1
rows.push({
sku,
status: 'mapped_source_backed_draft',
previous,
mappedRef: refs[0],
allCandidateRefs: refs.join(' | '),
complianceGate: evidence.complianceGate || ''
})
} else {
// Deliberately leave blank rather than adding a fake or generic clinical claim.
product.metafields.pdpClinicallyShownTo = ''
unmapped += 1
rows.push({
sku,
status: 'unmapped_no_source_backed_claim',
previous,
mappedRef: '',
allCandidateRefs: '',
complianceGate: evidence.complianceGate || 'missing_claims_evidence'
})
}
product.updatedAt = now
writeJson(path, product)
const workflowPath = join(workflowRoot, `${sku}.json`)
if (existsSync(workflowPath)) {
const workflow = readJson(workflowPath, {})
workflow.fields = workflow.fields || {}
workflow.fields.pdpClinicallyShownTo = workflow.fields.pdpClinicallyShownTo || {}
workflow.fields.pdpClinicallyShownTo.value = product.metafields.pdpClinicallyShownTo
workflow.fields.pdpClinicallyShownTo.status = product.metafields.pdpClinicallyShownTo
? 'needs_human_compliance_approval'
: 'blocked_no_source_backed_claim'
workflow.fields.pdpClinicallyShownTo.citations = claims.map((claim: any) => claim.citation?.source_url).filter(Boolean)
workflow.approval = { ...(workflow.approval || {}), compliance: product.approval.compliance || 'blocked' }
workflow.events = Array.isArray(workflow.events) ? workflow.events : []
workflow.events.unshift({
at: now,
type: 'clinical_claim_mapping_refresh',
actor: 'sync-clinically-shown-claims.ts',
field: 'pdpClinicallyShownTo',
from: previous,
to: product.metafields.pdpClinicallyShownTo,
summary: product.metafields.pdpClinicallyShownTo
? 'Mapped source-backed draft claim reference; human compliance approval still required.'
: 'No source-backed claim matched; left clinically_shown_to blank.'
})
workflow.updatedAt = now
writeJson(workflowPath, workflow)
}
}
const headers = ['sku', 'status', 'previous', 'mappedRef', 'allCandidateRefs', 'complianceGate']
const esc = (value: any) => /[",\n\r]/.test(String(value ?? '')) ? `"${String(value ?? '').replace(/"/g, '""')}"` : String(value ?? '')
await Bun.write(join(outRoot, 'clinical_claim_mapping_report.csv'), [headers.join(','), ...rows.map(row => headers.map(header => esc(row[header])).join(','))].join('\n') + '\n')
writeJson(join(outRoot, 'clinical_claim_mapping_report.json'), {
generatedAt: now,
sourceLibrary: 'data/sources/claims/claims-library.json',
totalProducts: rows.length,
sourceBackedClaimMetaobjects: meta.definitions.clinically_shown_to.length,
mappedProducts: mapped,
unmappedProducts: unmapped,
caveat: 'Only SKUs with source-backed claim evidence were mapped. Unmatched SKUs remain blank; no generic/fake clinical claim was created.',
rows
})
console.log(`Source-backed claim metaobjects: ${meta.definitions.clinically_shown_to.length}`)
console.log(`Mapped products: ${mapped}`)
console.log(`Unmapped products: ${unmapped}`)