/** Build an offline report from an explicitly captured public snapshot. No network requests. */
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const folder = path.join(root, 'docs/workshop-report');
const snapshot = JSON.parse(fs.readFileSync(path.join(folder, 'snapshot-20261103.json'), 'utf8'));
const args = process.argv.slice(2);
if (args.length && (args.length !== 2 || args[0] !== '--out' || !path.isAbsolute(args[1]))) throw Error('Use --out ABSOLUTE_HTML_FILE');
const out = args[1] || path.join(folder, 'report-20261104.html');
const escape = v => String(v).replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"');
const n = v => Number(v).toLocaleString('en-US');
const count = snapshot.publicSnapshot.counts;
const modes = snapshot.publicSnapshot.distributions.artifact.dataMode;
const base = snapshot.demo.baseline, ext = snapshot.demo.extension;
const total = o => Object.values(o).reduce((sum, v) => sum + v, 0);
if (total(base) !== 334 || total(ext) !== 16446 || !snapshot.publicSnapshot.complete) throw Error('UNEXPECTED_SNAPSHOT');
const artifactLabels = {
opportunity_card: '机会卡类成果', pain_list: '痛点清单', competitor_report: '竞品研究',
concept: '产品概念', assessment_report: '验证评估', category_report: '品类研究', voc_report: '用户声音',
};
const baseLabels = { groups: '小组', members: '成员', ideas: '创意', sources: '来源', evidence: '基础引文', opportunities: '机会卡',
projects: '项目', conceptVersions: '方案版本', reports: '报告', questions: '未决问题', validationTasks: '验证任务', assignments: '作业' };
const extLabels = { voices: ['虚构用户声音', '人群、场景、口味与条件检索'], observations: ['商品观察', '产品与规格比较'],
prices: ['价格快照', '同一商品多个时间与条件'], citations: ['新增引文', '同源原文与结论回查'], researchTasks: ['研究任务', '补证、负责人、执行状态'],
collaborationRecords: ['协作记录', '多人分工、评论与接力'] };
const skillCommands = [
['员工与会话', 'workshop-start', '绑定当前员工、Agent、小组和工作坊会话'],
['称呼', 'employee-name', '读取、保存或修改本人称呼;记住明确跳过'],
['可选通讯录', 'employee-read', '只读查询通讯录姓名;依赖管理员配置,当前未接通'],
['阶段成果', 'workshop-save', '保存报告、材料关联、未决问题,可生成机会卡'],
['项目', 'project-create / project-progress', '从机会建立项目,记录阶段推进、受阻或课堂完成'],
['概念方案', 'concept-save / project-status', '保存方案版本;回读项目成果、方案和事件'],
['资料入库', 'workshop-import', '按合同保存原料、工艺、竞品、证据等资料'],
['查重与检索', 'workshop-dedup / workshop-search', '精确查重、检索已有资料与报告'],
['回读与合同', 'workshop-read / workshop-contract', '按真实编号回读;核对服务支持字段'],
['正式报告', 'report-preview / report-submit', '建立预览;本人完成服务端确认后提交'],
['兼容入口', 'ingest / status / demo / connection', '沿用原文导入、状态、示例和连接检查'],
];
const baseEntries = Object.entries(base);
const localTime = new Intl.DateTimeFormat('zh-CN', { timeZone: 'Asia/Shanghai', dateStyle: 'medium', timeStyle: 'short', hour12: false }).format(new Date(snapshot.generatedAt));
const replacements = {
SNAPSHOT_TIME: escape(localTime + '(北京时间)'),
PUBLIC_KPIS: [['artifact', '份', '阶段成果'], ['project', '个', '项目'], ['opportunity', '张', '独立机会卡'], ['source', '个', '来源'], ['session', '个', '工作坊会话'], ['insight', '条', '洞察']]
.map(([key, unit, label]) => `
${escape(command)}