056c47581f
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>
268 lines
40 KiB
TypeScript
268 lines
40 KiB
TypeScript
#!/usr/bin/env bun
|
|
import { existsSync, statSync, writeFileSync } from 'fs'
|
|
import { join } from 'path'
|
|
|
|
const root = process.cwd()
|
|
const outRoot = join(root, 'content_population_exports')
|
|
const migrationOutRoot = join(root, '..', 'JV Migration to shopify', 'content_population_exports')
|
|
const dailyStatusDate = new Intl.DateTimeFormat('en-CA', {
|
|
timeZone: 'Asia/Kuala_Lumpur',
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit'
|
|
}).format(new Date())
|
|
|
|
function csv(rows: any[], headers: string[]) {
|
|
const esc = (value: any) => {
|
|
if (value === undefined || value === null) value = ''
|
|
value = Array.isArray(value) ? value.join(' | ') : String(value)
|
|
return /[",\n\r]/.test(value) ? `"${value.replace(/"/g, '""')}"` : value
|
|
}
|
|
return [headers.join(','), ...rows.map(row => headers.map(header => esc(row[header])).join(','))].join('\n') + '\n'
|
|
}
|
|
|
|
function fileRow(group: string, file: string, purpose: string, readiness: string, owner: string, base = outRoot) {
|
|
const path = join(base, file)
|
|
const present = existsSync(path)
|
|
const stat = present ? statSync(path) : null
|
|
return {
|
|
Group: group,
|
|
File: file,
|
|
Purpose: purpose,
|
|
Owner: owner,
|
|
ReadinessUse: readiness,
|
|
Present: present ? 'yes' : 'no',
|
|
SizeBytes: stat?.size || 0,
|
|
LastModified: stat?.mtime?.toISOString() || '',
|
|
Path: path
|
|
}
|
|
}
|
|
|
|
const rows = [
|
|
fileRow('Dashboard handoff CSV', 'products_content_matrixify.csv', 'Dashboard-side product Matrixify preview.', 'Import only after all blockers are zero.', 'Dashboard'),
|
|
fileRow('Dashboard handoff CSV', 'metaobjects_matrixify.csv', 'Dashboard-side metaobject Matrixify preview.', 'Import only after source-backed claims/assets are ready.', 'Dashboard'),
|
|
fileRow('Dashboard handoff CSV', 'smart_collections_matrixify.csv', 'Dashboard-side smart collection promo-card mapping preview.', 'Import after promo cards are approved.', 'Dashboard'),
|
|
fileRow('Dashboard blockers', 'export_blockers.csv', 'Full product/metaobject blocker list.', 'Must be empty before Lewis/Euan handoff.', 'Dashboard'),
|
|
fileRow('Dashboard blockers', 'handoff_manifest.json', 'Machine-readable handoff readiness manifest.', 'readyForLewis must be true.', 'Dashboard'),
|
|
fileRow('Dashboard blockers', 'handoff_summary.md', 'Human handoff summary.', 'Use for status only, not as proof of readiness.', 'Dashboard'),
|
|
fileRow('External source requests', 'source_request_pack.md', 'Human-readable source request packet.', 'Send to source owners while blocked.', 'Research / compliance / image'),
|
|
fileRow('External source requests', 'source_request_items.csv', 'Raw evidence/source drop request rows.', 'Use to collect Amazon/Trustpilot/Reddit drops.', 'Research'),
|
|
fileRow('External source requests', 'clinical_claims_request.csv', 'Clinical/regulatory evidence request rows.', 'Use to populate claims-library.json.', 'Compliance'),
|
|
fileRow('External source requests', 'image_production_brief.csv', 'PDP image production queue.', 'Use to produce/upload asset filenames.', 'Design'),
|
|
fileRow('Source acquisition', 'source_acquisition_plan.md', 'Staged provider recommendation and spend guardrails.', 'Use before any paid DataForSEO or Apify run.', 'Research'),
|
|
fileRow('Source acquisition', 'source_acquisition_targets.csv', 'Provider target queue by SKU/brand.', 'Use to batch source collection without credit burn.', 'Research'),
|
|
fileRow('Source acquisition', 'source_acquisition_spend_gate.md', 'Provider spend gate status.', 'Must explicitly allow provider spend before DataForSEO or Apify is run.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_spend_gate.csv', 'Provider spend gate check rows.', 'Use to see exactly which prerequisites block provider spend.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_spend_gate.json', 'Machine-readable provider spend gate status.', 'Export Console/API read this before paid provider usage.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_budget_gate.md', 'Provider budget cap gate status.', 'Must explicitly cap max spend/tasks before approval or provider subscription.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_budget_gate.csv', 'Provider budget cap check rows.', 'Use to see which budget caps still block paid usage.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_budget_gate.json', 'Machine-readable provider budget cap status.', 'Export Console/API read this before paid provider usage.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_cost_plan.md', 'Provider cost-estimate plan for staged paid runs.', 'Must record current pricing and keep estimates within max spend before approval.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_cost_plan.csv', 'Provider cost-plan check rows.', 'Use to see which pricing/estimate fields still block paid usage.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_cost_plan.json', 'Machine-readable provider cost-plan status.', 'Export Console/API read this before paid provider usage.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_approval_gate.md', 'Provider approval file validation status.', 'Must validate local approval files before any paid provider usage.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_approval_gate.csv', 'Provider approval check rows.', 'Use to see which approval fields still block paid usage.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_approval_gate.json', 'Machine-readable provider approval gate status.', 'Export Console/API read this before paid provider usage.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_control_run.md', 'One-command source acquisition packet refresh status.', 'Use to regenerate all staged provider packet artifacts without spending credits.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_control_run.csv', 'Source acquisition packet refresh step rows.', 'Use to identify packet-generation failures.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_control_run.json', 'Machine-readable source acquisition packet refresh status.', 'Export Console/API read this for packet freshness.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_next_actions.md', 'Sequenced DataForSEO-first / Apify-selective execution checklist.', 'Use as the immediate operating list before any provider subscription or credit spend.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_next_actions.csv', 'Source acquisition next-action rows with owners, stop rules, and spend status.', 'Use to assign the next no-spend and approval tasks.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_next_actions.json', 'Machine-readable source acquisition next-action status.', 'Export Console/API read this to show the current provider-spend instruction.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_subscription_decision.md', 'Plain-English provider subscription decision packet.', 'Use to decide whether to subscribe now without accidentally enabling spend.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_subscription_decision.csv', 'Subscription decision rows by provider.', 'Use to see why DataForSEO is wait/not-yet and Apify is held.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_subscription_decision.json', 'Machine-readable subscription decision status.', 'Export Console/API read this for the current subscribe/spend recommendation.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_pricing_references.md', 'Official pricing-reference summary for staged provider decisions.', 'Use to fill the local cost plan from sourced pricing, not guesses.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_pricing_references.csv', 'Provider pricing reference rows.', 'Use to copy source URLs, checked timestamps, and caveats into cost planning.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_pricing_references.json', 'Machine-readable provider pricing references.', 'Export Console/API read this before budget/cost approval.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_cost_scenarios.md', 'No-spend capped pilot cost scenarios.', 'Use to choose a tiny staged cap without enabling spend.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_cost_scenarios.csv', 'Cost scenario rows by provider/stage.', 'Use to compare standard DataForSEO, priority DataForSEO, and held Apify scenarios.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'source_acquisition_cost_scenarios.json', 'Machine-readable capped cost scenarios.', 'Export Console/API read this before budget/cost approval.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'apify_gapfill_runbook.md', 'Stage 2 Apify selective gap-fill runbook.', 'Use only after DataForSEO pilot review shows a named gap.', 'Research'),
|
|
fileRow('Source acquisition', 'apify_gapfill_targets.csv', 'Apify run/hold target queue and spend caps.', 'Run only first-batch targets before dataset inspection.', 'Research'),
|
|
fileRow('Source acquisition', 'apify_gapfill_manifest.json', 'Machine-readable Apify gap-fill packet status.', 'Export Console/API read this before any Apify spend.', 'Research'),
|
|
fileRow('Source acquisition', 'apify_competitor_pdp_input_template.json', 'No-spend Apify actor input template for first batch.', 'Paste into chosen actor only after approval to run Stage 2.', 'Research'),
|
|
fileRow('Source acquisition', 'apify_task_preflight.md', 'Final local guard before paid Apify actor execution.', 'Must be ready before any Apify actor run.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'apify_task_preflight.csv', 'Apify paid actor preflight check rows.', 'Use to see which final paid-run checks are still blocked.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'apify_task_preflight.json', 'Machine-readable Apify paid actor preflight.', 'Export Console/API read this before any paid Apify usage.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_pilot_plan.md', 'Stage 1 DataForSEO pilot instructions.', 'Run only after ASINs are filled and reviewed.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_pilot_manifest.json', 'Machine-readable DataForSEO pilot status.', 'Ready task count must be reviewed before any paid call.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_pilot_targets.csv', 'Stage 1 DataForSEO ASIN intake queue.', 'Fill ASINs before creating task payload.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_lookup_queue.md', 'No-spend manual ASIN lookup workflow.', 'Use to fill the Stage 1 ASIN map before paid task creation.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_lookup_queue.csv', 'No-spend ASIN lookup URLs and actions.', 'Use to confirm exact Amazon product matches without API credit spend.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_lookup_queue.json', 'Machine-readable ASIN lookup queue status.', 'Export Console/API read this before paid task creation.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_candidate_report.md', 'No-spend ASIN candidate evidence report.', 'Use as lookup aid only; candidates still require Amazon confirmation before paid tasks.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_candidate_report.csv', 'ASIN candidate evidence rows.', 'Use to see candidate confidence, source URL, and promotion blockers.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_candidate_report.json', 'Machine-readable ASIN candidate status.', 'Export Console/API can read this without treating candidates as paid-task ready.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_web_evidence.md', 'No-spend public web evidence report for ASIN lookup.', 'Use to separate third-party ASIN hints and rejected leads from Amazon-confirmed matches.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_web_evidence.csv', 'ASIN public web evidence rows.', 'Use to avoid rechecking weak leads while keeping third-party evidence out of paid payloads.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_web_evidence.json', 'Machine-readable ASIN public web evidence status.', 'Export Console/API read this before treating public evidence as promotion-safe.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_unresolved_asin_evidence.md', 'No-spend negative evidence report for unresolved ASINs from live DataForSEO product results.', 'Use to prove unresolved SKUs stay out of the paid Reviews payload instead of guessing.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_unresolved_asin_evidence.csv', 'Unresolved ASIN candidate/rejection rows.', 'Use to inspect top candidates and exact-match counts for missing ASINs.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_unresolved_asin_evidence.json', 'Machine-readable unresolved ASIN evidence status.', 'Export Console/API read this to show anti-guessing evidence for missing ASINs.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_confirmation_report.md', 'Manual Amazon-page ASIN confirmation report.', 'Use to prove candidate ASINs were checked against visible Amazon title/brand/product/pack evidence.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_confirmation_report.csv', 'ASIN confirmation validation rows.', 'Use to see which confirmations are ready for promotion and why others are blocked.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_confirmation_report.json', 'Machine-readable ASIN confirmation status.', 'Promotion and Export Console read this before copying any candidate into the ASIN map.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_promotion_report.md', 'Safe ASIN promotion report.', 'Copies only Amazon-confirmed/high-confidence candidates into asin-map; blocked rows explain why no payload was created.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_promotion_report.csv', 'ASIN promotion check rows.', 'Use to review which candidates were promoted or blocked.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_asin_promotion_report.json', 'Machine-readable ASIN promotion status.', 'Export Console/API read this before DataForSEO payload generation.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_amazon_reviews_task_payload.json', 'DataForSEO task payload generated from ASIN map.', 'Keep empty until ASINs are supplied; cap first run.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_amazon_reviews_curl_template.sh', 'Credential-safe curl template for task creation.', 'Use shell env credentials only; do not commit secrets.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_task_preflight.md', 'Final local guard before paid DataForSEO task creation.', 'Must be ready before manually running the curl template.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_task_preflight.csv', 'DataForSEO paid task preflight check rows.', 'Use to see which final paid-run checks are still blocked.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_task_preflight.json', 'Machine-readable DataForSEO paid task preflight.', 'Export Console/API read this before any paid DataForSEO usage.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_support_response_gate.md', 'DataForSEO support response validation gate.', 'Use after support replies to prove endpoint availability or replacement path before any capped retry.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_support_response_gate.csv', 'Support response gate check rows.', 'Use to see which provider-response fields still block retry.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_support_response_gate.json', 'Machine-readable support response gate status.', 'Export Console/API read this before treating provider endpoint availability as resolved.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_reviews_docs_status.md', 'Official DataForSEO Amazon Reviews documentation status.', 'Use to prove whether the provider currently documents the Reviews endpoint as unavailable before any retry.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_reviews_docs_status.csv', 'Official docs status check rows.', 'Use to see fetched-docs reachability, endpoint mention, and temporary-unavailable detection.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_reviews_docs_status.json', 'Machine-readable official docs status.', 'Export Console/API read this to keep provider outage evidence current without credentials or paid calls.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_stage1_approval_request.md', 'Project-owner approval request packet for the capped DataForSEO Stage 1 pilot.', 'Use only after provider endpoint availability is confirmed; this is not approval by itself.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_stage1_approval_request.csv', 'Approval request readiness rows.', 'Use to see whether payload, budget, cost, endpoint, and approval are ready.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_stage1_approval_request.json', 'Machine-readable approval request packet.', 'Export Console/API read this to show the exact approval values without storing secrets.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'manual_amazon_review_capture.md', 'No-spend manual Amazon review capture fallback queue.', 'Use if DataForSEO Reviews remains blocked; save completed JSON source drops into data/sources/amazon/.', 'Research'),
|
|
fileRow('Source acquisition', 'manual_amazon_review_capture.csv', 'Manual Amazon capture rows by ASIN.', 'Use to assign capture targets and source-drop save paths.', 'Research'),
|
|
fileRow('Source acquisition', 'manual_amazon_review_capture.json', 'Machine-readable manual Amazon capture queue.', 'Export Console/API read this to show no-spend fallback targets.', 'Research'),
|
|
fileRow('Source acquisition', 'manual_amazon_review_capture_validation.md', 'Manual Amazon capture completion gate.', 'Use to prove listed manual source drops exist and contain valid review evidence before treating fallback as complete.', 'Research'),
|
|
fileRow('Source acquisition', 'manual_amazon_review_capture_validation.csv', 'Manual Amazon capture validation rows by ASIN.', 'Use to see missing/invalid fallback source drops and per-file review counts.', 'Research'),
|
|
fileRow('Source acquisition', 'manual_amazon_review_capture_validation.json', 'Machine-readable manual Amazon capture completion status.', 'Export Console/API read this to distinguish queued fallback work from completed source evidence.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_ingest_validation.md', 'DataForSEO raw result ingest validation.', 'Use after the paid pilot to prove raw results were normalized into Amazon source drops.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_ingest_validation.csv', 'DataForSEO ingest output rows.', 'Shows converted Amazon source files and review counts.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_ingest_validation.json', 'Machine-readable DataForSEO ingest status.', 'Export Console/API read this before source validation.', 'Research'),
|
|
fileRow('Source acquisition', 'dataforseo_pilot_review.md', 'DataForSEO pilot output review gate.', 'Must be complete before scaling DataForSEO or enabling Apify gap-fill.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_pilot_review.csv', 'DataForSEO pilot review check rows.', 'Use to see why scale-up or Apify remains blocked.', 'Research / project owner'),
|
|
fileRow('Source acquisition', 'dataforseo_pilot_review.json', 'Machine-readable DataForSEO pilot review decision.', 'Export Console/API read this before scale-up decisions.', 'Research / project owner'),
|
|
fileRow('Validation', 'asset_manifest_validation.csv', 'Required/missing asset validation.', 'Must have zero missing uploads/references.', 'Dashboard / design'),
|
|
fileRow('Validation', 'draft_pdp_asset_generation.csv', 'Generated draft PDP PNG asset ledger.', 'Use to verify the 570 product PDP image filenames exist as review-marked draft assets; image approval is still required.', 'Dashboard / design'),
|
|
fileRow('Validation', 'draft_pdp_asset_generation.json', 'Machine-readable generated draft PDP PNG asset ledger.', 'Export/review evidence for generated draft product imagery without claiming final creative approval.', 'Dashboard / design'),
|
|
fileRow('Validation', 'metaobject_svg_asset_generation.csv', 'Generated metaobject SVG asset ledger.', 'Use to verify metaobject icon/image files were produced in the asset root; product PDP images are still separate.', 'Dashboard / design'),
|
|
fileRow('Validation', 'metaobject_svg_asset_generation.json', 'Machine-readable generated metaobject SVG asset ledger.', 'Export/review evidence for the 16 SVG files produced locally without treating missing PDP images as complete.', 'Dashboard / design'),
|
|
fileRow('Validation', 'template_schema_validation.csv', 'Template header match evidence.', 'Must pass before import.', 'Dashboard'),
|
|
fileRow('Validation', 'source_drop_validation.csv', 'Source drop validation status.', 'Must pass before full intelligence generation.', 'Research'),
|
|
fileRow('Validation', 'claims_library_validation.csv', 'Claims-library validation status.', 'Must pass before clinical claims content.', 'Compliance'),
|
|
fileRow('Validation', 'clinical_claim_mapping_report.csv', 'SKU-level clinically_shown_to mapping report.', 'Use to verify only source-backed claims were mapped and unmatched SKUs stayed blank instead of receiving fake claims.', 'Compliance / dashboard'),
|
|
fileRow('Validation', 'clinical_claim_mapping_report.json', 'Machine-readable clinically_shown_to mapping report.', 'Export Console/reviewer evidence for mapped vs unmapped claim coverage.', 'Compliance / dashboard'),
|
|
fileRow('Validation', 'unmatched_claims_review_packet.md', 'Human-readable queue for SKUs with blank clinically_shown_to fields.', 'Use for compliance review; do not auto-fill generic claims.', 'Compliance'),
|
|
fileRow('Validation', 'unmatched_claims_review_packet.csv', 'SKU-level unmatched clinical-claim review rows.', 'Use to assign the remaining compliance decisions.', 'Compliance'),
|
|
fileRow('Validation', 'unmatched_claims_review_packet.json', 'Machine-readable unmatched clinical-claim review queue.', 'Export Console/reviewer evidence for unresolved compliance decisions.', 'Compliance'),
|
|
fileRow('Validation', 'clinical_blank_decision_template.md', 'Human-readable approval template for intentionally blank clinical-claim fields.', 'Use only when compliance approves omitting clinically_shown_to for a SKU.', 'Compliance'),
|
|
fileRow('Validation', 'clinical_blank_decision_template.csv', 'Clinical blank-decision validation rows.', 'Use to see pending/valid approved_blank decisions.', 'Compliance'),
|
|
fileRow('Validation', 'clinical_blank_decision_template.json', 'Machine-readable clinical blank-decision gate.', 'Dashboard and migration exporters read valid approvals before clearing missing-claim blockers.', 'Compliance'),
|
|
fileRow('Validation', 'product_approval_review_packet.md', 'Human-readable product approval queue summary.', 'Use to route human review without self-approving products.', 'Umar / JV reviewer'),
|
|
fileRow('Validation', 'product_approval_review_packet.csv', 'Product-level approval blocker rows.', 'Use to approve content/compliance/image/export lanes by SKU.', 'Umar / JV reviewer'),
|
|
fileRow('Validation', 'product_approval_review_packet.json', 'Machine-readable product approval review queue.', 'Export Console/reviewer evidence for unresolved approval decisions.', 'Umar / JV reviewer'),
|
|
fileRow('Validation', 'product_approval_decision_gate.md', 'Human-readable product approval decision gate.', 'Use after human review to apply explicit approval decisions from the editable JSON file.', 'Umar / JV reviewer'),
|
|
fileRow('Validation', 'product_approval_decision_gate.csv', 'Product approval decision validation rows.', 'Use to see which approval decisions are valid/applicable.', 'Umar / JV reviewer'),
|
|
fileRow('Validation', 'product_approval_decision_gate.json', 'Machine-readable product approval decision gate.', 'Export Console/API read this before approvals can clear handoff blockers.', 'Umar / JV reviewer'),
|
|
fileRow('Validation', 'content_population_readiness.md', 'Consolidated readiness audit.', 'Must report ready YES.', 'Dashboard'),
|
|
fileRow('Validation', 'handoff_verification_run.md', 'Master verification run.', 'Must report ready YES and all checks pass.', 'Dashboard'),
|
|
fileRow('Intelligence', 'intelligence_generation_workqueue.csv', 'Per-SKU missing intelligence task queue.', 'Must be empty/pass before full catalogue approval.', 'Dashboard intelligence lane'),
|
|
fileRow('Intelligence', 'intelligence_generation_by_sku.csv', 'SKU-prioritized intelligence queue.', 'Use to batch full-catalogue generation.', 'Dashboard intelligence lane'),
|
|
fileRow('Intelligence', 'intelligence_generation_summary.csv', 'Per-view intelligence coverage summary.', 'Every view must be 190/190.', 'Dashboard intelligence lane'),
|
|
fileRow('Handoff orchestration', 'handoff_action_plan.md', 'Owner-facing action list.', 'All actions must be closed before handoff.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_packet_refresh.md', 'One-command no-spend handoff packet refresh report.', 'Use to prove all packet artifacts can be regenerated while still surfacing expected blockers.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_packet_refresh.json', 'Machine-readable one-command handoff packet refresh report.', 'Export Console/API can read this for packet freshness and blocked-vs-failed status.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_packet_refresh.csv', 'Handoff packet refresh step rows.', 'Use to inspect which packet steps passed, are expected blockers, or failed to refresh.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_artifact_freshness.md', 'Artifact freshness report for refresh-scoped handoff files.', 'Use to distinguish packet completeness from current-run freshness.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_artifact_freshness.json', 'Machine-readable artifact freshness report.', 'Export Console/API read this to catch stale refresh-scoped artifacts.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_artifact_freshness.csv', 'Artifact freshness rows by delivery file.', 'Use to inspect stale, missing, fresh, and static-allowed packet files.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'executive_decision_brief.md', 'Executive decision brief for Umar/Lewis/Euan.', 'Use to close named decisions and owner blockers before staging handoff.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'executive_decision_brief.json', 'Machine-readable executive decision brief.', 'Export Console/API read this for current decision status.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'executive_decision_brief_decisions.csv', 'Decision rows with owners/evidence files.', 'Use to assign required approvals and compliance decisions.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'executive_decision_brief_readiness.csv', 'Readiness snapshot metrics for decision brief.', 'Use as meeting snapshot alongside the decision brief.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'blocker_burndown.md', 'Evidence-based blocker burn-down summary.', 'Use to track exactly what remains before handoff readiness can pass.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'blocker_burndown.json', 'Machine-readable blocker burn-down.', 'Export Console/API read this for remaining evidence counts.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'blocker_burndown.csv', 'Blocker burn-down rows by lane.', 'Use to track remaining compliance, approval, and staging evidence counts.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'blocker_burndown_next_actions.csv', 'Ordered next actions from blocker burn-down.', 'Use to assign the next evidence-producing tasks.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_evidence_dossier.md', 'Strict requirement-to-evidence completion dossier.', 'Use to prove which master-plan requirements are satisfied vs blocked before claiming completion.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_evidence_dossier.json', 'Machine-readable requirement-to-evidence completion dossier.', 'Export Console/API read this for completion-audit evidence.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_evidence_dossier.csv', 'Requirement evidence rows with proof and remaining work.', 'Use to audit every requirement area before handoff.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'reviewer_decision_workbook.md', 'Owner-facing workbook for remaining compliance, approval, provider, and staging decisions.', 'Use to hand reviewers exact editable files, required fields, commands, and guardrails.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'reviewer_decision_workbook.json', 'Machine-readable reviewer decision workbook.', 'Export Console/API read this for owner-lane status.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'reviewer_decision_workbook.csv', 'Reviewer decision workbook rows by owner lane.', 'Use to assign remaining human/provider/staging decisions.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'reviewer_completion_commands.csv', 'Exact regeneration command sequence after reviewer files are filled.', 'Use to rerun gates after human/provider/staging evidence lands.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'reviewer_input_preflight.md', 'Preflight report for reviewer-owned editable input files.', 'Use before rerunning heavier gates to catch incomplete compliance, approval, provider, and staging inputs.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'reviewer_input_preflight.json', 'Machine-readable reviewer input preflight.', 'Export Console/API read this to show which editable input files are still missing or incomplete.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'reviewer_input_preflight.csv', 'Reviewer input preflight rows by input file.', 'Use to route exact missing fields back to reviewers before gate reruns.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'owner_handoff_messages.md', 'Copy-paste owner handoff messages for remaining evidence blockers.', 'Use to send compliance, approval, staging, and provider-spend owners exact asks without inventing approvals.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'owner_handoff_messages.json', 'Machine-readable owner handoff message packet.', 'Export Console/API read this for owner-specific message status and guardrails.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'owner_handoff_messages.csv', 'Owner handoff message rows.', 'Use to copy exact owner asks, editable files, preflight evidence, and rerun commands.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'owner_response_intake.md', 'Owner reply/evidence intake tracker validation.', 'Use after sending owner messages to record replies and evidence updates before rerunning gates.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'owner_response_intake.json', 'Machine-readable owner response intake status.', 'Export Console/API read this to show whether owner replies/evidence updates have been recorded.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'owner_response_intake.csv', 'Owner response intake rows by lane.', 'Use to inspect sent/response/evidence/command status per owner lane.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_gate_dependency_map.md', 'Master verifier gate-to-owner dependency map.', 'Use to route blocked verifier gates to exact owner inputs instead of rerunning blindly.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_gate_dependency_map.json', 'Machine-readable handoff gate dependency map.', 'Export Console/API read this to show blocked gates, owners, and unblocking inputs.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_gate_dependency_map.csv', 'Gate dependency rows by verifier check.', 'Use to inspect command, owner, blockers, and rerun command per gate.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'handoff_gate_dependency_by_owner.csv', 'Blocked verifier gates grouped by owner.', 'Use to brief owners on which verifier gates their evidence unblocks.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'post_owner_response_rerun_plan.md', 'Safe rerun plan after owner responses/evidence updates.', 'Use only after owner response intake marks a lane ready for gate rerun.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'post_owner_response_rerun_plan.json', 'Machine-readable post-owner response rerun plan.', 'Export Console/API read this to show which lane command sequences are safe to rerun.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'post_owner_response_rerun_plan.csv', 'Post-owner response rerun rows by lane.', 'Use to inspect held/runnable lane command sequences and guardrails.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'owner_evidence_acceptance_guide.md', 'Acceptance guide for owner-editable evidence files.', 'Use to show reviewers exactly what counts as valid evidence without approving anything.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'owner_evidence_acceptance_guide.json', 'Machine-readable owner evidence acceptance guide.', 'Export Console/API read this to show valid/invalid evidence criteria per blocker lane.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'owner_evidence_acceptance_guide.csv', 'Owner evidence acceptance rows by lane.', 'Use to inspect required fields, valid examples, invalid examples, and validators.', 'Project owner'),
|
|
fileRow('Handoff orchestration', `daily_status_${dailyStatusDate}.md`, 'Current daily handoff status snapshot.', 'Use as the dated operating snapshot; not proof of final readiness.', 'Project owner'),
|
|
fileRow('Handoff orchestration', `daily_status_${dailyStatusDate}.json`, 'Machine-readable current daily handoff status snapshot.', 'Export Console/API can read this for dated blocker and DataForSEO status.', 'Project owner'),
|
|
fileRow('Handoff orchestration', `daily_status_${dailyStatusDate}.csv`, 'Daily status rows by area.', 'Use to brief owners on current blockers and next actions.', 'Project owner'),
|
|
fileRow('Handoff orchestration', 'staging_handoff_packet.md', 'Lewis/Euan staging handoff packet.', 'Use to send exact import files, sequence, current blockers, and PDP spot-check queue.', 'Project owner + Lewis/Euan'),
|
|
fileRow('Handoff orchestration', 'staging_handoff_packet.json', 'Machine-readable staging handoff packet.', 'Export Console/API read this for staging handoff status.', 'Project owner + Lewis/Euan'),
|
|
fileRow('Handoff orchestration', 'staging_handoff_import_files.csv', 'Staging import file manifest.', 'Use to confirm exact Matrixify file paths and import order.', 'Lewis/Euan'),
|
|
fileRow('Handoff orchestration', 'staging_pdp_spot_check_queue.csv', 'Queued PDP spot-check sample.', 'Use to assign real staging URL checks; queue is not completed evidence.', 'Project owner + Lewis/Euan'),
|
|
fileRow('Handoff orchestration', 'staging_handoff_actions.csv', 'Staging handoff action rows.', 'Use to assign remaining blocker and staging evidence work.', 'Project owner + Lewis/Euan'),
|
|
fileRow('Handoff orchestration', 'staging_import_checklist.md', 'Preflight/import/PDP/cutover checklist.', 'All blocking rows must be resolved.', 'Project owner + Lewis/Euan'),
|
|
fileRow('Handoff orchestration', 'staging_evidence_validation.md', 'Staging evidence validator output.', 'Must pass with clean import logs, 5+ PDP checks, cutover approval.', 'Project owner + Lewis/Euan'),
|
|
fileRow('Handoff orchestration', 'staging_evidence_intake.md', 'Staging evidence intake initializer report.', 'Use to confirm editable staging evidence intake paths exist without fake import/PDP evidence.', 'Project owner + Lewis/Euan'),
|
|
fileRow('Handoff orchestration', 'staging_evidence_intake.json', 'Machine-readable staging evidence intake initializer status.', 'Export Console/API read this to show pending staging evidence intake paths.', 'Project owner + Lewis/Euan'),
|
|
fileRow('Handoff orchestration', 'staging_evidence_intake.csv', 'Staging evidence intake rows.', 'Use to see which intake files/folders were initialized and what still requires real staging activity.', 'Project owner + Lewis/Euan'),
|
|
fileRow('Migration CSV', 'products_content_v5.csv', 'Lewis/Euan product/variant Matrixify import candidate.', 'Import after dashboard handoff is ready.', 'Migration emitter', migrationOutRoot),
|
|
fileRow('Migration CSV', 'products_content_v5_blockers.csv', 'Migration product blocker list.', 'Must be empty before import.', 'Migration emitter', migrationOutRoot),
|
|
fileRow('Migration CSV', 'metaobjects_all.csv', 'Migration metaobject import candidate.', 'Import before products after readiness passes.', 'Migration emitter', migrationOutRoot),
|
|
fileRow('Migration CSV', 'smart_collections_promo_cards.csv', 'Migration smart collection promo-card import candidate.', 'Import after promo cards exist.', 'Migration emitter', migrationOutRoot),
|
|
fileRow('Migration validation', 'asset_manifest_validation.csv', 'Migration-side asset validation.', 'Must have zero missing uploads/references.', 'Migration emitter', migrationOutRoot)
|
|
]
|
|
|
|
const generatedAt = new Date().toISOString()
|
|
const missing = rows.filter(row => row.Present !== 'yes')
|
|
const manifest = {
|
|
generatedAt,
|
|
ready: missing.length === 0,
|
|
counts: {
|
|
files: rows.length,
|
|
present: rows.length - missing.length,
|
|
missing: missing.length
|
|
},
|
|
groups: [...new Set(rows.map(row => row.Group))].map(group => ({
|
|
group,
|
|
files: rows.filter(row => row.Group === group).length,
|
|
present: rows.filter(row => row.Group === group && row.Present === 'yes').length
|
|
})),
|
|
files: rows
|
|
}
|
|
|
|
writeFileSync(join(outRoot, 'delivery_index.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf8')
|
|
writeFileSync(join(outRoot, 'delivery_index.csv'), csv(rows, ['Group', 'File', 'Purpose', 'Owner', 'ReadinessUse', 'Present', 'SizeBytes', 'LastModified', 'Path']), 'utf8')
|
|
|
|
const md = [
|
|
'# JV delivery index',
|
|
'',
|
|
`Generated: ${generatedAt}`,
|
|
'',
|
|
'This index is the map of every handoff, blocker, validation, source-request, intelligence, staging, and migration artifact needed to move from dashboard preview to Lewis/Euan staging import.',
|
|
'',
|
|
`Files present: ${manifest.counts.present}/${manifest.counts.files}`,
|
|
'',
|
|
'## Groups',
|
|
...manifest.groups.map(row => `- ${row.group}: ${row.present}/${row.files} present`),
|
|
'',
|
|
'## Files',
|
|
...rows.map(row => `- ${row.Present === 'yes' ? '[present]' : '[missing]'} **${row.Group}** / \`${row.File}\` - ${row.Purpose} Owner: ${row.Owner}. Readiness use: ${row.ReadinessUse}`),
|
|
'',
|
|
'## Final readiness rule',
|
|
'`delivery_index` only proves the packet exists. Final readiness still requires `bun run verify:handoff` to pass and Lewis/Euan staging evidence to be recorded.',
|
|
''
|
|
].join('\n')
|
|
writeFileSync(join(outRoot, 'delivery_index.md'), md, 'utf8')
|
|
|
|
console.log(`Delivery index ready: ${manifest.ready}`)
|
|
console.log(`Files present: ${manifest.counts.present}/${manifest.counts.files}`)
|
|
if (!manifest.ready) process.exitCode = 1
|