| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 |
- import fs from 'node:fs';
- import assert from 'node:assert/strict';
- import path from 'node:path';
- const out = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Za-z]:)/, '$1'));
- const root = 'docs/workshop-dialogue-r13-20261110';
- const keys = ['R05','R03','R13'];
- const records = Object.fromEntries(keys.map(key => [key, JSON.parse(fs.readFileSync(`${root}/evidence/reused-${key}.json`,'utf8')).record]));
- const old = fs.readFileSync(`${root}/阶段产出/15-proposal.txt`,'utf8').split(/\r?\n/).find(line => line.startsWith('建议:'));
- assert.ok(old);
- const discussion = [
- ['现有材料确认了什么','同一三味六碗商品下,已保存评价存在尝新满意、偏回经典、特定味型不喜欢等不同表达。这是有内容的偏好分歧;不是目标宿舍人群的偏好分布,也不能计算某种组合的需求率。'],
- ['原推导缺哪一环','偏好分歧至少有几种解释:部分人更喜欢经典味,部分人不喜欢某款味型,或固定装箱不能贴合个人选择。现有三条记录不能区分这些解释;R03只说辣椒味不好吃,没有说明因辣度、香气或其他感官原因。'],
- ['修订后的当前建议','保留原三味为有效基准,先判断问题来自味型本身还是购买组合。“经典红烧3碗+探索蒜香海鲜3碗”保留为研究者提出的比较原型;现有材料没有证明3∶3最优、跨系列混装可行或用户更愿选择,不将其提升为主推新品。'],
- ['反证怎样改变建议','R13肯定三种风味和原组合,说明减少味型可能损失已有收益。因此要按偏好与任务区分适用条件,不能用两条分歧覆盖满意体验;若现有单味/组合已满足任务,就先复用现品而非新增SKU。'],
- ['对研发的实际含义','先区分两个决定:是否需要改变味型体验,以及是否只需改变选择组合。前者需要受控感官比较,后者需要等条件的选择比较;只换组合不能证明味型改善,口号喜好也不能证明产品收益。当前不指定新配方,也不从评论推断面体或酱料的因果机制。'],
- ];
- const rows = [
- ['R05','支持“该记录偏好经典”,不能证明整箱陌生造成购买障碍、需要两味或3∶3。'],
- ['R03','支持“该记录不喜欢其中味型”,不能直接归因辣度或证明组合结构有问题。'],
- ['R13','支持“该记录认可三味与现有体验”;实际削弱面向所有人的减味建议,保留原三味对照。'],
- ];
- const trial = [
- ['问题','味型偏好与装箱选择,哪一项造成现方案不足?以下为待执行设计,不是测试结果。'],
- ['准备','先核正式标签、当前可售单味/混合装和可获得样品。现有目录是历史资料,不能当当前库存或保证同价可买。'],
- ['组合比较','在相关购买任务中比较现有三味、已核可售单味/组合与拟议3∶3原型;总件数、价格条件、信息量尽量一致,呈现顺序平衡。无法统一的条件单列,不隐藏差价。记录选择、不选、理由及接受的代价,价格未知不声称愿付。'],
- ['感官比较','若要判断具体味型问题,以核实后的单碗样品在相同制备条件下盲码比较,分开记录香气、辣感、酱感和质构等实际相关维度,再询问整体取舍;未核实因果前不指定某种工艺修复。'],
- ['结果分支','现有可售方案已满足任务→复用现品;组合存在独特价值→再核混装与经营条件;偏好主要由味型体验解释→转相应感官问题;只有新颖印象、无选择理由→修改或暂缓该原型。'],
- ['执行条件','需要核实的样品、真实相关用户、受控制备条件和记录表。人数、排期、效果阈值需随研究目的和实际基准确认,本示例未获得,不承诺统计结论。'],
- ];
- const evidence = Object.fromEntries(keys.map(key => [key, {sourceId:'preview-'+key,claim:rows.find(row => row[0]===key)[1],quotes:[{text:records[key].content,ref:`京东|商品 ${records[key].product_id}|评价日 ${records[key].review_date_raw}|购买规格 ${records[key].purchased_sku_text}|评价ID ${records[key].review_id};链接为商品页,非单条评价直链`}]}]));
- const report = {
- title:'拌面概念提案内容修订示例:经典与探索组合的依据是否充分',
- subtitle:'沿用原课题、报告方向和候选;仅修订论证与证据表达。复用2026-11-10已存材料,未重新采集或执行消费者测试。',
- executive:[discussion[2][1], '本页是局部内容修订示例,不是新一轮完整工作坊或已验证的商业提案。'],
- delivery:{schema:'ksf.workshop-delivery.v1',moduleId:'D2-08',kind:'proposal',contentStatus:'draft',outputs:['proposal']},
- chapters:[
- {id:'product-proposal',title:'从原建议到有依据的当前判断',stage:'S5',sections:[{kind:'para',title:'原记录中的建议(逐字引用)',text:old},...discussion.map(([title,text])=>({kind:'para',title,text}))]},
- {id:'original-evidence',title:'实际原句怎样支持或限制判断',stage:'S5',sections:[{kind:'para',text:'下列三条是为了讨论不同解释而选的既有记录,不是随机样本,也不据此计算比例。来源真实性及用户身份未独立验证;引用内容逐字来自本地已存记录。'}, {kind:'findings',data:keys.map(key=>({id:key,evidence:key,conclusion:rows.find(row=>row[0]===key)[1],attitude:'研究解释与原句分开展示;相反材料改变建议的范围和验证安排。'}))}]},
- {id:'next-test',title:'可交接的下一项判别',stage:'S5',sections:[{kind:'table',data:{cols:['项目','内容与决策作用'],rows:trial}}]},
- ], evidence,
- };
- const raw = {session:[],artifact:[{objectId:'argument-preview',title:report.title,ownerName:'本地修订示例',dataMode:'sample',stageCode:'S5',artifactType:'concept',report,rawText:discussion.map(([title,text])=>title+'\n'+text).join('\n\n')}],source:keys.map(key=>({objectId:'preview-'+key,title:`${key} 京东三味六碗商品评价`,sourceUrl:records[key].parentProduct.url,rawText:records[key].content,dataMode:'sample'})),opportunity:[],project:[],insight:[]};
- fs.writeFileSync(path.join(out,'example-fixture.json'),JSON.stringify(raw,null,2)+'\n');
- const esc = value=>String(value).replace(/[&<>"']/g,char=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[char]));
- const md = '# '+report.title+'\n\n'+report.subtitle+'\n\n## 原建议(原文)\n\n'+old+'\n\n'+discussion.map(([title,text])=>'## '+title+'\n\n'+text).join('\n\n')+'\n\n## 关键原句\n\n'+keys.map(key=>'### '+key+'\n\n> '+records[key].content+'\n\n'+evidence[key].quotes[0].ref+'\n\n'+rows.find(row=>row[0]===key)[1]+'\n\n原记录:'+`${root}/evidence/reused-${key}.json`).join('\n\n')+'\n\n## 待执行验证\n\n'+trial.map(([title,text])=>'**'+title+'**:'+text).join('\n\n')+'\n';
- fs.writeFileSync(path.join(out,'报告内容修订示例.md'),md);
- const html='<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>'+esc(report.title)+'</title><style>body{font:16px/1.85 system-ui,sans-serif;color:#26323e;margin:28px auto;padding:0 18px;max-width:900px;overflow-wrap:anywhere}h1{font-size:26px;line-height:1.5}h2{font-size:21px;margin-top:30px}blockquote{margin:12px 0;padding:12px 16px;background:#f2f5f8;border-left:3px solid #7d8e9e;white-space:pre-wrap}small{display:block;line-height:1.8;color:#556575}a{color:#22589a}section{border-bottom:1px solid #ddd;padding-bottom:18px}.note{background:#fff7df;padding:12px}dt{font-weight:650}dd{margin:4px 0 16px}</style><h1>'+esc(report.title)+'</h1><p class="note">'+esc(report.subtitle)+' 这是局部内容修订示例,不替代完整研究验收。</p><h2>原记录的建议</h2><blockquote>'+esc(old)+'</blockquote>'+discussion.map(([title,text])=>'<section><h2>'+esc(title)+'</h2><p>'+esc(text)+'</p></section>').join('')+'<h2>关键原句与分析</h2><p>三条为解释差异而选的既有记录,不是随机样本;不计算需求率。来源真实性及用户身份未独立验证。</p>'+keys.map(key=>'<section id="'+key+'"><h3>'+key+'</h3><blockquote>'+esc(records[key].content)+'</blockquote><small>'+esc(evidence[key].quotes[0].ref)+'</small><p>'+esc(rows.find(row=>row[0]===key)[1])+'</p><a href="../workshop-dialogue-r13-20261110/evidence/reused-'+key+'.json">查看本地原记录</a> · <a href="'+esc(records[key].parentProduct.url)+'" target="_blank" rel="noopener noreferrer">商品来源页(非评价直链)</a></section>').join('')+'<h2>可交接的下一项判别(待执行)</h2><dl>'+trial.map(([title,text])=>'<dt>'+esc(title)+'</dt><dd>'+esc(text)+'</dd>').join('')+'</dl></html>';
- fs.writeFileSync(path.join(out,'报告内容修订示例.html'),html);
- console.log(JSON.stringify({report:report.title,archivedRecords:keys,productionWrites:0,liveCollection:false,consumerTestExecuted:false}));
|